home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / PARSTXTR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-27  |  79.4 KB  |  3,297 lines

  1. /****************************************************************************
  2. *                parstxtr.c
  3. *
  4. *  This module parses textures and atmosphere effects.
  5. *
  6. *  from Persistence of Vision(tm) Ray Tracer
  7. *  Copyright 1996 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23.  
  24. #include "frame.h"
  25. #include "vector.h"
  26. #include "povproto.h"
  27. #include "parse.h"
  28. #include "parstxtr.h"
  29. #include "colour.h"
  30. #include "express.h"
  31. #include "gif.h"
  32. #include "halos.h"
  33. #include "iff.h"
  34. #include "image.h"
  35. #include "matrices.h" 
  36. #include "normal.h"   
  37. #include "pigment.h"  
  38. #include "povray.h"
  39. #include "pgm.h"
  40. #include "ppm.h"
  41. #include "targa.h"
  42. #include "png_pov.h"
  43. #include "texture.h"
  44. #include "tokenize.h"
  45.  
  46.  
  47. /*****************************************************************************
  48. * Local preprocessor defines
  49. ******************************************************************************/
  50.  
  51. #define ADD_TNORMAL if (Tnormal == NULL) {if ((Default_Texture->Tnormal) != NULL) \
  52.  Tnormal = Copy_Tnormal ((Default_Texture->Tnormal)); else Tnormal = Create_Tnormal ();\
  53.  Texture->Tnormal=Tnormal;};
  54.  
  55. /*****************************************************************************
  56. * Local typedefs
  57. ******************************************************************************/
  58.  
  59.  
  60.  
  61. /*****************************************************************************
  62. * Local variables
  63. ******************************************************************************/
  64.  
  65. TEXTURE *Default_Texture;
  66.  
  67.  
  68.  
  69. /*****************************************************************************
  70. * Static functions
  71. ******************************************************************************/
  72.  
  73. static void Parse_Bump_Map PARAMS((TNORMAL *Tnormal));
  74. static void Parse_Image_Map PARAMS((PIGMENT *Pigment));
  75. static void Parse_Pattern PARAMS((TPATTERN *New, int TPat_Type));
  76. static TEXTURE *Parse_Vers1_Texture PARAMS((void));
  77. static TEXTURE *Parse_Tiles PARAMS((void));
  78. static TEXTURE *Parse_Material_Map PARAMS((void));
  79. static void Parse_Texture_Transform PARAMS((TEXTURE *Texture));
  80. static TURB *Check_Turb PARAMS((WARP **Warps_Ptr));
  81. static void Parse_Warp PARAMS((WARP **Warp_Ptr));
  82. static void Check_BH_Parameters PARAMS((BLACK_HOLE *bh));
  83.  
  84.  
  85.  
  86. /*****************************************************************************
  87. *
  88. * FUNCTION
  89. *
  90. * INPUT
  91. *
  92. * OUTPUT
  93. *
  94. * RETURNS
  95. *
  96. * AUTHOR
  97. *
  98. *   POV-Ray Team
  99. *   
  100. * DESCRIPTION
  101. *
  102. * CHANGES
  103. *
  104. ******************************************************************************/
  105.  
  106. IMAGE *Parse_Image (Legal)
  107.   int Legal;
  108.   {
  109.    IMAGE *Image;
  110.    VECTOR Local_Vector;
  111.    char *Name;
  112.  
  113.    Image = Create_Image ();
  114.  
  115.    Image->Image_Type = Legal;
  116.  
  117.    if (Legal & GRAD_FILE)
  118.      {
  119.       EXPECT
  120.         CASE_VECTOR
  121.           Warn(1.5, "Should use map_type keyword and/or eliminate orientation.");
  122.           Have_Vector = FALSE;
  123.           Parse_Vector_Float (Local_Vector);
  124.           if (Have_Vector)
  125.             Assign_Vector(Image->Gradient,Local_Vector);
  126.           else
  127.             Image->Map_Type = (int)Local_Vector[X];
  128.         END_CASE
  129.  
  130.         OTHERWISE
  131.           UNGET
  132.           EXIT
  133.         END_CASE
  134.       END_EXPECT
  135.      }
  136.  
  137.    EXPECT
  138.      CASE (IFF_TOKEN)
  139.        Image->File_Type = IFF_FILE;
  140.        Name=Parse_String();
  141.        Read_Iff_Image (Image, Name);
  142.        POV_FREE(Name);
  143.        EXIT
  144.      END_CASE
  145.  
  146.      CASE (GIF_TOKEN)
  147.        Image->File_Type = GIF_FILE;
  148.        Name=Parse_String();
  149.        Read_Gif_Image(Image, Name);
  150.        POV_FREE(Name);
  151.        EXIT
  152.      END_CASE
  153.  
  154.      CASE (POT_TOKEN)
  155.        Image->File_Type = POT_FILE;
  156.        Name=Parse_String();
  157.        Read_Gif_Image(Image, Name);
  158.        POV_FREE(Name);
  159.        EXIT
  160.      END_CASE
  161.  
  162.      CASE (SYS_TOKEN)
  163.        Image->File_Type = SYS_FILE;
  164.        Name=Parse_String();
  165.        READ_SYS_IMAGE(Image, Name);
  166.        POV_FREE(Name);
  167.        EXIT
  168.      END_CASE
  169.  
  170.      CASE (TGA_TOKEN)
  171.        Image->File_Type = TGA_FILE;
  172.        Name=Parse_String();
  173.        Read_Targa_Image(Image, Name);
  174.        POV_FREE(Name);
  175.        EXIT
  176.      END_CASE
  177.  
  178.      CASE (PNG_TOKEN)
  179.        Image->File_Type = PNG_FILE;
  180.        Name=Parse_String();
  181.        Read_Png_Image(Image, Name);
  182.        POV_FREE(Name);
  183.        EXIT
  184.      END_CASE
  185.  
  186.      CASE (PGM_TOKEN)
  187.        Image->File_Type = PGM_FILE;
  188.        Name=Parse_String();
  189.        Read_PGM_Image(Image, Name);
  190.        POV_FREE(Name);
  191.        EXIT
  192.      END_CASE
  193.  
  194.      CASE (PPM_TOKEN)
  195.        Image->File_Type = PPM_FILE;
  196.        Name=Parse_String();
  197.        Read_PPM_Image(Image, Name);
  198.        POV_FREE(Name);
  199.        EXIT
  200.      END_CASE
  201.  
  202.      OTHERWISE
  203.        Parse_Error_Str ("map file spec");
  204.      END_CASE
  205.    END_EXPECT
  206.  
  207.    if (!(Image->File_Type & Legal))
  208.      Error ("File type not supported here.");
  209.    return (Image);
  210.   }
  211.  
  212.  
  213.  
  214. /*****************************************************************************
  215. *
  216. * FUNCTION
  217. *
  218. * INPUT
  219. *
  220. * OUTPUT
  221. *
  222. * RETURNS
  223. *
  224. * AUTHOR
  225. *
  226. *   POV-Ray Team
  227. *   
  228. * DESCRIPTION
  229. *
  230. * CHANGES
  231. *
  232. ******************************************************************************/
  233.  
  234. static void Parse_Image_Map (Pigment)
  235. PIGMENT *Pigment;
  236.   {
  237.    int reg;
  238.    IMAGE *Image;
  239.    
  240.    Parse_Begin();
  241.  
  242.    Image = Parse_Image (IMAGE_FILE);
  243.    Image->Use_Colour_Flag = TRUE;
  244.  
  245.    EXPECT                   /* Look for image_attribs */
  246.      CASE (ONCE_TOKEN)
  247.        Image->Once_Flag=TRUE;
  248.      END_CASE
  249.  
  250.      CASE (INTERPOLATE_TOKEN)
  251.        Image->Interpolation_Type = (int)Parse_Float();
  252.      END_CASE
  253.  
  254.      CASE (MAP_TYPE_TOKEN)
  255.        Image->Map_Type = (int) Parse_Float ();
  256.      END_CASE
  257.  
  258.      CASE (USE_COLOUR_TOKEN)
  259.        Image->Use_Colour_Flag = TRUE;
  260.      END_CASE
  261.  
  262.      CASE (USE_INDEX_TOKEN)
  263.        Image->Use_Colour_Flag = FALSE;
  264.      END_CASE
  265.  
  266.      CASE (ALPHA_TOKEN)
  267.        Warn(1.55, "Keyword ALPHA discontinued. Use FILTER instead.");
  268.  
  269.      CASE (COLOUR_KEY_TOKEN)
  270.        switch(Token.Function_Id)
  271.          {
  272.           case FILTER_TOKEN:
  273.             EXPECT
  274.               CASE (ALL_TOKEN)
  275.                 {
  276.                  DBL filter;
  277.                  filter = Parse_Float();
  278.                  for (reg = 0 ; reg < Image->Colour_Map_Size ; reg++)
  279.                    Image->Colour_Map[reg].Filter
  280.                        = (unsigned short) (filter *255.0);
  281.                 }
  282.                 EXIT
  283.               END_CASE
  284.  
  285.               OTHERWISE
  286.                 UNGET
  287.                 reg = (int)(Parse_Float() + 0.01);
  288.                 if (Image->Colour_Map == NULL)
  289.                   Not_With ("filter","non color-mapped image");
  290.                 if ((reg < 0) || (reg >= Image->Colour_Map_Size))
  291.                   Error ("FILTER color register value out of range.");
  292.  
  293.                 Parse_Comma();
  294.                 Image->Colour_Map[reg].Filter
  295.                        = (unsigned short) (255.0 * Parse_Float());
  296.                 EXIT
  297.               END_CASE
  298.  
  299.             END_EXPECT
  300.             Pigment->Flags |= HAS_FILTER;
  301.             break;
  302.  
  303.           case TRANSMIT_TOKEN:
  304.             EXPECT
  305.               CASE (ALL_TOKEN)
  306.                 {
  307.                  DBL transmit;
  308.                  transmit = Parse_Float();
  309.                  for (reg = 0 ; reg < Image->Colour_Map_Size ; reg++)
  310.                    Image->Colour_Map[reg].Transmit
  311.                        = (unsigned short) (transmit *255.0);
  312.                 }
  313.                 EXIT
  314.               END_CASE
  315.  
  316.               OTHERWISE
  317.                 UNGET
  318.                 reg = (int)(Parse_Float() + 0.01);
  319.                 if (Image->Colour_Map == NULL)
  320.                   Not_With ("transmit","non color-mapped image");
  321.                 if ((reg < 0) || (reg >= Image->Colour_Map_Size))
  322.                   Error ("TRANSMIT color register value out of range.");
  323.  
  324.                 Parse_Comma();
  325.                 Image->Colour_Map[reg].Transmit
  326.                        = (unsigned short) (255.0 * Parse_Float());
  327.                 EXIT
  328.               END_CASE
  329.  
  330.             END_EXPECT
  331.             Pigment->Flags |= HAS_FILTER;
  332.             break;
  333.  
  334.           default:
  335.             UNGET
  336.             Parse_Error_Str ("filter or transmit");
  337.             break;
  338.          }
  339.      END_CASE
  340.  
  341.      OTHERWISE
  342.        UNGET
  343.        EXIT
  344.      END_CASE
  345.    END_EXPECT
  346.    
  347.    Pigment->Vals.Image=Image;
  348.    Parse_End();
  349. }
  350.  
  351.  
  352.  
  353. /*****************************************************************************
  354. *
  355. * FUNCTION
  356. *
  357. * INPUT
  358. *
  359. * OUTPUT
  360. *
  361. * RETURNS
  362. *
  363. * AUTHOR
  364. *
  365. *   POV-Ray Team
  366. *   
  367. * DESCRIPTION
  368. *
  369. * CHANGES
  370. *
  371. ******************************************************************************/
  372.  
  373. static void Parse_Bump_Map (Tnormal)
  374. TNORMAL *Tnormal;
  375.   {
  376.    IMAGE *Image;
  377.  
  378.    Parse_Begin();
  379.  
  380.    Image = Parse_Image(IMAGE_FILE);
  381.    Image->Use_Colour_Flag = TRUE;
  382.  
  383.    EXPECT
  384.      CASE (ONCE_TOKEN)
  385.        Image->Once_Flag=TRUE;
  386.      END_CASE
  387.  
  388.      CASE (MAP_TYPE_TOKEN)
  389.        Image->Map_Type = (int) Parse_Float ();
  390.      END_CASE
  391.  
  392.      CASE (INTERPOLATE_TOKEN)
  393.        Image->Interpolation_Type = (int)Parse_Float();
  394.      END_CASE
  395.  
  396.      CASE (BUMP_SIZE_TOKEN)
  397.        Tnormal->Amount = Parse_Float ();
  398.      END_CASE
  399.  
  400.      CASE (USE_COLOUR_TOKEN)
  401.        Image->Use_Colour_Flag = TRUE;
  402.      END_CASE
  403.  
  404.      CASE (USE_INDEX_TOKEN)
  405.        Image->Use_Colour_Flag = FALSE;
  406.      END_CASE
  407.  
  408.      OTHERWISE
  409.        UNGET
  410.        EXIT
  411.      END_CASE
  412.    END_EXPECT
  413.  
  414.    Tnormal->Vals.Image=Image;
  415.  
  416.    Parse_End();
  417. }
  418.  
  419.  
  420.  
  421. /*****************************************************************************
  422. *
  423. * FUNCTION
  424. *
  425. * INPUT
  426. *
  427. * OUTPUT
  428. *
  429. * RETURNS
  430. *
  431. * AUTHOR
  432. *
  433. *   POV-Ray Team
  434. *
  435. * DESCRIPTION
  436. *
  437. * CHANGES
  438. *
  439. ******************************************************************************/
  440.  
  441. void Parse_Pigment (Pigment_Ptr)
  442.   PIGMENT **Pigment_Ptr;
  443.   {
  444.    EXPECT            /* Look for [pigment_id] */
  445.      CASE (PIGMENT_ID_TOKEN)
  446.        Destroy_Pigment(*Pigment_Ptr);
  447.        *Pigment_Ptr = Copy_Pigment ((PIGMENT *) Token.Constant_Data);
  448.        EXIT
  449.      END_CASE
  450.  
  451.      OTHERWISE
  452.        UNGET
  453.        EXIT
  454.      END_CASE
  455.    END_EXPECT    /* End pigment_id */
  456.    
  457.    Parse_Pattern((TPATTERN *)(*Pigment_Ptr),PIGMENT_TYPE);
  458.  
  459.    if (Not_In_Default && ((*Pigment_Ptr)->Type == NO_PATTERN))
  460.    {
  461.      Warn(1.7, "Pigment type unspecified or not 1st item.");
  462.    }
  463.   }
  464.  
  465.  
  466.  
  467. /*****************************************************************************
  468. *
  469. * FUNCTION
  470. *
  471. * INPUT
  472. *
  473. * OUTPUT
  474. *
  475. * RETURNS
  476. *
  477. * AUTHOR
  478. *
  479. *   POV-Ray Team
  480. *
  481. * DESCRIPTION
  482. *
  483. * CHANGES
  484. *
  485. ******************************************************************************/
  486.  
  487. static void Parse_Pattern (New, TPat_Type)
  488.   TPATTERN *New;
  489.   int TPat_Type;
  490.   {
  491.    VECTOR Local_Vector;
  492.    COLOUR Local_Colour;
  493.    MATRIX Local_Matrix;
  494.    TRANSFORM Local_Trans;
  495.    TURB *Local_Turb;
  496.    unsigned short Old_Type=New->Type;
  497.    IMAGE *Old_Image = NULL;
  498.  
  499.    if (Old_Type==BITMAP_PATTERN)
  500.    {
  501.      Old_Image=New->Vals.Image;
  502.    }
  503.  
  504.    EXPECT
  505.      CASE (AGATE_TOKEN)
  506.        New->Type = AGATE_PATTERN;
  507.        Check_Turb(&(New->Warps));
  508.        New->Vals.Agate_Turb_Scale = 1.0;
  509.        EXIT
  510.      END_CASE
  511.  
  512.      CASE (BOZO_TOKEN)
  513.        New->Type = BOZO_PATTERN;
  514.        EXIT
  515.      END_CASE
  516.  
  517.      CASE (GRANITE_TOKEN)
  518.        New->Type = GRANITE_PATTERN;
  519.        EXIT
  520.      END_CASE
  521.  
  522.      CASE (LEOPARD_TOKEN)
  523.        New->Type = LEOPARD_PATTERN;
  524.        EXIT
  525.      END_CASE
  526.  
  527.      CASE (MARBLE_TOKEN)
  528.        New->Type = MARBLE_PATTERN;
  529.        New->Wave_Type = TRIANGLE_WAVE;
  530.        EXIT
  531.      END_CASE
  532.  
  533.      CASE (MANDEL_TOKEN)
  534.        New->Type = MANDEL_PATTERN;
  535.        New->Vals.Iterations = (int)Parse_Float();
  536.        EXIT
  537.      END_CASE
  538.  
  539.      CASE (ONION_TOKEN)
  540.        New->Type = ONION_PATTERN;
  541.        EXIT
  542.      END_CASE
  543.  
  544.      CASE (PATTERN1_TOKEN)
  545.        New->Type = PATTERN1_PATTERN;
  546.        EXIT
  547.      END_CASE
  548.  
  549.      CASE (PATTERN2_TOKEN)
  550.        New->Type = PATTERN2_PATTERN;
  551.        EXIT
  552.      END_CASE
  553.  
  554.      CASE (PATTERN3_TOKEN)
  555.        New->Type = PATTERN3_PATTERN;
  556.        EXIT
  557.      END_CASE
  558.  
  559.      CASE (BUMPY1_TOKEN)
  560.        if (TPat_Type != NORMAL_TYPE)
  561.        {
  562.          Only_In("bumpy1","normal");
  563.        }
  564.        New->Type = BUMPY1_PATTERN;
  565.        EXIT
  566.      END_CASE
  567.  
  568.      CASE (BUMPY2_TOKEN)
  569.        if (TPat_Type != NORMAL_TYPE)
  570.        {
  571.          Only_In("bumpy2","normal");
  572.        }
  573.        New->Type = BUMPY2_PATTERN;
  574.        EXIT
  575.      END_CASE
  576.  
  577.      CASE (BUMPY3_TOKEN)
  578.        if (TPat_Type != NORMAL_TYPE)
  579.        {
  580.          Only_In("bumpy3","normal");
  581.        }
  582.        New->Type = BUMPY3_PATTERN;
  583.        EXIT
  584.      END_CASE
  585.  
  586.      CASE (SPIRAL1_TOKEN)
  587.        New->Type = SPIRAL1_PATTERN;
  588.        New->Vals.Arms = (short)Parse_Float ();
  589.        New->Wave_Type = TRIANGLE_WAVE;
  590.        EXIT
  591.      END_CASE
  592.  
  593.      CASE (SPIRAL2_TOKEN)
  594.        New->Type = SPIRAL2_PATTERN;
  595.        New->Vals.Arms = (short)Parse_Float ();
  596.        New->Wave_Type = TRIANGLE_WAVE;
  597.        EXIT
  598.      END_CASE
  599.  
  600.      CASE (SPOTTED_TOKEN)
  601.        New->Type = SPOTTED_PATTERN;
  602.        EXIT
  603.      END_CASE
  604.  
  605.      CASE (WOOD_TOKEN)
  606.        New->Type = WOOD_PATTERN;
  607.        New->Wave_Type = TRIANGLE_WAVE;
  608.        EXIT
  609.      END_CASE
  610.  
  611.      CASE (GRADIENT_TOKEN)
  612.        New->Type = GRADIENT_PATTERN;
  613.        Parse_Vector (New->Vals.Gradient);
  614.        EXIT
  615.      END_CASE
  616.  
  617.      CASE (RADIAL_TOKEN)
  618.        New->Type = RADIAL_PATTERN;
  619.        EXIT
  620.      END_CASE
  621.  
  622.      CASE (CRACKLE_TOKEN)
  623.        New->Type = CRACKLE_PATTERN;
  624.        EXIT
  625.      END_CASE
  626.  
  627.      CASE_COLOUR
  628.        if (TPat_Type != PIGMENT_TYPE)
  629.        {
  630.          Only_In("color","pigment");
  631.        }
  632.        New->Type = PLAIN_PATTERN;
  633.        Parse_Colour (((PIGMENT *)New)->Colour);
  634.        EXIT
  635.      END_CASE
  636.  
  637.      CASE (CHECKER_TOKEN)
  638.        New->Type = CHECKER_PATTERN;
  639.        New->Frequency = 0.0;
  640.        Destroy_Blend_Map(New->Blend_Map);
  641.        New->Blend_Map = Parse_Blend_List(2,&Check_Default_Map,TPat_Type);
  642.        EXIT
  643.      END_CASE
  644.  
  645.      CASE (BRICK_TOKEN)
  646.        if (New->Type!=BRICK_PATTERN)
  647.        {
  648.          Make_Vector(New->Vals.Brick.Size,8.0,3.0,4.5);
  649.          New->Vals.Brick.Mortar=0.5-Small_Tolerance*2.0;
  650.        New->Type = BRICK_PATTERN;
  651.        }
  652.        New->Frequency = 0.0;
  653.        Destroy_Blend_Map(New->Blend_Map);
  654.        New->Blend_Map = Parse_Blend_List(2,&Brick_Default_Map,TPat_Type);
  655.        EXIT
  656.      END_CASE
  657.  
  658.      CASE (HEXAGON_TOKEN)
  659.        New->Type = HEXAGON_PATTERN;
  660.        New->Frequency = 0.0;
  661.        Destroy_Blend_Map(New->Blend_Map);
  662.        New->Blend_Map = Parse_Blend_List(3,&Hex_Default_Map,TPat_Type);
  663.        EXIT
  664.      END_CASE
  665.  
  666.      CASE (IMAGE_MAP_TOKEN)
  667.        if (TPat_Type != PIGMENT_TYPE)
  668.        {
  669.          Only_In("image_map","pigment");
  670.        }
  671.  
  672.        if (Old_Type==BITMAP_PATTERN) 
  673.        {
  674.          Destroy_Image(Old_Image);
  675.        }   
  676.  
  677.        New->Type = BITMAP_PATTERN;
  678.        New->Frequency = 0.0;
  679.        Parse_Image_Map ((PIGMENT *)New);
  680.        EXIT
  681.      END_CASE
  682.  
  683.      CASE (BUMP_MAP_TOKEN)
  684.        if (TPat_Type != NORMAL_TYPE)
  685.        {
  686.          Only_In("bump_map","normal");
  687.        }
  688.  
  689.        if (Old_Type==BITMAP_PATTERN) 
  690.        {
  691.          Destroy_Image(Old_Image);
  692.        }   
  693.  
  694.        New->Type = BITMAP_PATTERN;
  695.        New->Frequency = 0.0;
  696.        Parse_Bump_Map ((TNORMAL *)New);
  697.        EXIT
  698.      END_CASE
  699.  
  700.      CASE (WAVES_TOKEN)
  701.        New->Type = WAVES_PATTERN;
  702.        EXIT
  703.      END_CASE
  704.  
  705.      CASE (RIPPLES_TOKEN)
  706.        New->Type = RIPPLES_PATTERN;
  707.        EXIT
  708.      END_CASE
  709.  
  710.      CASE (WRINKLES_TOKEN)
  711.        New->Type = WRINKLES_PATTERN;
  712.        EXIT
  713.      END_CASE
  714.  
  715.      CASE (BUMPS_TOKEN)
  716.        New->Type = BUMPS_PATTERN;
  717.        EXIT
  718.      END_CASE
  719.  
  720.      CASE (DENTS_TOKEN)
  721.        New->Type = DENTS_PATTERN;
  722.        EXIT
  723.      END_CASE
  724.  
  725.      CASE (QUILTED_TOKEN)
  726.        New->Type = QUILTED_PATTERN;
  727.        New->Vals.Quilted.Control0 = 1.0;
  728.        New->Vals.Quilted.Control1 = 1.0;
  729.        New->Frequency = 0.0;
  730.        EXIT
  731.      END_CASE
  732.  
  733.      CASE (AVERAGE_TOKEN)
  734.        New->Type = AVERAGE_PATTERN;
  735.        EXIT
  736.      END_CASE
  737.  
  738.      OTHERWISE
  739.        UNGET
  740.        EXIT
  741.      END_CASE
  742.    END_EXPECT     /* Concludes pattern_body */
  743.  
  744.    if ((Old_Type==BITMAP_PATTERN) && (New->Type!=BITMAP_PATTERN))
  745.    {
  746.      Destroy_Image(Old_Image);
  747.    }   
  748.  
  749.    if (TPat_Type == NORMAL_TYPE) 
  750.     {
  751.      Parse_Comma();
  752.      ((TNORMAL *)New)->Amount = Allow_Float (((TNORMAL *)New)->Amount );
  753.     }
  754.  
  755.    EXPECT         /* Look for pattern_modifier */
  756.      CASE (TURBULENCE_TOKEN)
  757.        Local_Turb=Check_Turb(&(New->Warps));
  758.        Parse_Vector_Float(Local_Turb->Turbulence);
  759.      END_CASE
  760.  
  761.      CASE (COLOUR_MAP_TOKEN)
  762.        if (TPat_Type != PIGMENT_TYPE)
  763.        {
  764.          Only_In("color_map","pigment");
  765.        }
  766.        if (New->Type == CHECKER_PATTERN ||
  767.            New->Type == BRICK_PATTERN ||
  768.            New->Type == HEXAGON_PATTERN ||
  769.            New->Type == PLAIN_PATTERN ||
  770.            New->Type == BITMAP_PATTERN)
  771.          Warn(1.5, "Cannot use color map with this pigment type.");
  772.        Destroy_Blend_Map(New->Blend_Map);
  773.        New->Blend_Map = Parse_Colour_Map ();
  774.      END_CASE
  775.  
  776.      CASE (PIGMENT_MAP_TOKEN)
  777.        if (TPat_Type != PIGMENT_TYPE)
  778.        {
  779.          Only_In("pigment_map","pigment");
  780.        }
  781.        if (New->Type == CHECKER_PATTERN ||
  782.            New->Type == BRICK_PATTERN ||
  783.            New->Type == HEXAGON_PATTERN ||
  784.            New->Type == PLAIN_PATTERN ||
  785.            New->Type == BITMAP_PATTERN)
  786.          Not_With ("pigment_map","this pigment type");
  787.        Destroy_Blend_Map(New->Blend_Map);
  788.        New->Blend_Map = Parse_Blend_Map (PIGMENT_TYPE,New->Type);
  789.      END_CASE
  790.  
  791.      CASE (SLOPE_MAP_TOKEN)
  792.        if (TPat_Type != NORMAL_TYPE)
  793.        {
  794.          Only_In("slope_map","normal");
  795.        }
  796.        if (New->Type == CHECKER_PATTERN ||
  797.            New->Type == BRICK_PATTERN ||
  798.            New->Type == HEXAGON_PATTERN ||
  799.            New->Type == PLAIN_PATTERN ||
  800.            New->Type == AVERAGE_PATTERN ||
  801.            New->Type == BITMAP_PATTERN)
  802.          Not_With ("slope_map","this normal type");
  803.        Destroy_Blend_Map(New->Blend_Map);
  804.        New->Blend_Map = Parse_Blend_Map (SLOPE_TYPE,New->Type);
  805.      END_CASE
  806.  
  807.      CASE (NORMAL_MAP_TOKEN)
  808.        if (TPat_Type != NORMAL_TYPE)
  809.        {
  810.          Only_In("normal_map","normal");
  811.        }
  812.        if (New->Type == CHECKER_PATTERN ||
  813.            New->Type == BRICK_PATTERN ||
  814.            New->Type == HEXAGON_PATTERN ||
  815.            New->Type == PLAIN_PATTERN ||
  816.            New->Type == BITMAP_PATTERN)
  817.          Not_With ("normal_map","this normal type");
  818.        Destroy_Blend_Map(New->Blend_Map);
  819.        New->Blend_Map = Parse_Blend_Map (NORMAL_TYPE,New->Type);
  820.      END_CASE
  821.  
  822.      CASE (TEXTURE_MAP_TOKEN)
  823.        if (TPat_Type != TEXTURE_TYPE)
  824.        {
  825.          Only_In("texture_map","texture");
  826.        }
  827.        if (New->Type == CHECKER_PATTERN ||
  828.            New->Type == BRICK_PATTERN ||
  829.            New->Type == HEXAGON_PATTERN ||
  830.            New->Type == PLAIN_PATTERN ||
  831.            New->Type == BITMAP_PATTERN)
  832.          Not_With ("texture_map","this pattern type");
  833.        Destroy_Blend_Map(New->Blend_Map);
  834.        New->Blend_Map = Parse_Blend_Map (TEXTURE_TYPE,New->Type);
  835.      END_CASE
  836.  
  837.      CASE (QUICK_COLOUR_TOKEN)
  838.        if (TPat_Type != PIGMENT_TYPE)
  839.        {
  840.          Only_In("quick_color","pigment");
  841.        }
  842.        Parse_Colour (Local_Colour);
  843.        if (opts.Quality_Flags & Q_QUICKC)
  844.        {
  845.           New->Type = PLAIN_PATTERN;
  846.           Assign_Colour(((PIGMENT *)New)->Colour,Local_Colour);
  847.        }
  848.      END_CASE
  849.  
  850.      CASE (CONTROL0_TOKEN)
  851.        if (New->Type == QUILTED_PATTERN) 
  852.        {
  853.          New->Vals.Quilted.Control0 = Parse_Float ();
  854.        }
  855.        else
  856.        {
  857.          Not_With ("control0","this normal");
  858.        }
  859.      END_CASE
  860.  
  861.      CASE (CONTROL1_TOKEN)
  862.        if (New->Type == QUILTED_PATTERN)
  863.        {
  864.          New->Vals.Quilted.Control1 = Parse_Float ();
  865.        }
  866.        else
  867.        {
  868.          Not_With ("control1","this normal");
  869.        }
  870.      END_CASE
  871.  
  872.      CASE (OCTAVES_TOKEN)
  873.        Local_Turb=Check_Turb(&(New->Warps));
  874.        Local_Turb->Octaves = (int)Parse_Float();
  875.        if(Local_Turb->Octaves < 1)
  876.           Local_Turb->Octaves = 1;
  877.        if(Local_Turb->Octaves > 10)  /* Avoid DOMAIN errors */
  878.           Local_Turb->Octaves = 10;
  879.      END_CASE
  880.  
  881.      CASE (OMEGA_TOKEN)
  882.        Local_Turb=Check_Turb(&(New->Warps));
  883.        Local_Turb->Omega = Parse_Float();
  884.      END_CASE
  885.  
  886.      CASE (LAMBDA_TOKEN)
  887.        Local_Turb=Check_Turb(&(New->Warps));
  888.        Local_Turb->Lambda = Parse_Float();
  889.      END_CASE
  890.  
  891.      CASE (FREQUENCY_TOKEN)
  892.        New->Frequency = Parse_Float();
  893.      END_CASE
  894.  
  895.      CASE (RAMP_WAVE_TOKEN)
  896.        New->Wave_Type = RAMP_WAVE;
  897.      END_CASE
  898.  
  899.      CASE (TRIANGLE_WAVE_TOKEN)
  900.        New->Wave_Type = TRIANGLE_WAVE;
  901.      END_CASE
  902.  
  903.      CASE (SINE_WAVE_TOKEN)
  904.        New->Wave_Type = SINE_WAVE;
  905.      END_CASE
  906.  
  907.      CASE (SCALLOP_WAVE_TOKEN)
  908.        New->Wave_Type = SCALLOP_WAVE;
  909.      END_CASE
  910.  
  911.      CASE (PHASE_TOKEN)
  912.        New->Phase = Parse_Float();
  913.      END_CASE
  914.  
  915.      CASE (BUMP_SIZE_TOKEN)
  916.        if (TPat_Type != NORMAL_TYPE)
  917.           Only_In ("bump_size","normal");
  918.        ((TNORMAL *)New)->Amount = Parse_Float ();
  919.      END_CASE
  920.  
  921.      CASE (AGATE_TURB_TOKEN)
  922.        if (New->Type != AGATE_PATTERN)
  923.           Not_With ("agate_turb","non-agate");
  924.        New->Vals.Agate_Turb_Scale = Parse_Float();
  925.        Check_Turb(&(New->Warps));   /* agate needs Octaves, Lambda etc. */
  926.      END_CASE
  927.  
  928.      CASE (BRICK_SIZE_TOKEN)
  929.        if (New->Type != BRICK_PATTERN)
  930.           Not_With ("brick_size","non-brick");
  931.        Parse_Vector(New->Vals.Brick.Size);
  932.      END_CASE
  933.  
  934.      CASE (MORTAR_TOKEN)
  935.        if (New->Type != BRICK_PATTERN)
  936.           Not_With ("mortar","non-brick");
  937.        New->Vals.Brick.Mortar = Parse_Float()-Small_Tolerance*2.0;
  938.      END_CASE
  939.  
  940.      CASE (WARP_TOKEN)
  941.        Parse_Warp(&(New->Warps));
  942.      END_CASE
  943.  
  944.      CASE (TRANSLATE_TOKEN)
  945.        Parse_Vector (Local_Vector);
  946.        Translate_Tpattern (New, Local_Vector);
  947.      END_CASE
  948.  
  949.      CASE (ROTATE_TOKEN)
  950.        Parse_Vector (Local_Vector);
  951.        Rotate_Tpattern (New, Local_Vector);
  952.      END_CASE
  953.  
  954.      CASE (SCALE_TOKEN)
  955.        Parse_Scale_Vector (Local_Vector);
  956.        Scale_Tpattern (New, Local_Vector);
  957.      END_CASE
  958.  
  959.      CASE (MATRIX_TOKEN)
  960.        Parse_Matrix(Local_Matrix);
  961.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  962.        Transform_Tpattern (New, &Local_Trans);
  963.      END_CASE
  964.  
  965.      CASE (TRANSFORM_TOKEN)
  966.        GET(TRANSFORM_ID_TOKEN)
  967.        Transform_Tpattern (New, (TRANSFORM *)Token.Constant_Data);
  968.      END_CASE
  969.  
  970.      OTHERWISE
  971.        UNGET
  972.        EXIT
  973.      END_CASE
  974.    END_EXPECT
  975.  
  976.    if ((TPat_Type==TEXTURE_TYPE) && (New->Type!=PLAIN_PATTERN) &&
  977.        (New->Blend_Map==NULL))
  978.    {
  979.       Error("Patterned texture must have texture_map.");
  980.    }
  981.   }
  982.  
  983.  
  984.  
  985. /*****************************************************************************
  986. *
  987. * FUNCTION
  988. *
  989. * INPUT
  990. *
  991. * OUTPUT
  992. *
  993. * RETURNS
  994. *
  995. * AUTHOR
  996. *
  997. *   POV-Ray Team
  998. *   
  999. * DESCRIPTION
  1000. *
  1001. * CHANGES
  1002. *
  1003. ******************************************************************************/
  1004.  
  1005. void Parse_Tnormal (Tnormal_Ptr)
  1006.   TNORMAL **Tnormal_Ptr;
  1007.   {
  1008.    EXPECT            /* Look for [tnormal_id] */
  1009.      CASE (TNORMAL_ID_TOKEN)
  1010.        Destroy_Tnormal(*Tnormal_Ptr);
  1011.        *Tnormal_Ptr = Copy_Tnormal ((TNORMAL *) Token.Constant_Data);
  1012.        EXIT
  1013.      END_CASE
  1014.  
  1015.      OTHERWISE
  1016.        UNGET
  1017.        EXIT
  1018.      END_CASE
  1019.    END_EXPECT    /* End [tnormal_id] */
  1020.  
  1021.    if (*Tnormal_Ptr == NULL)
  1022.      if ((Default_Texture->Tnormal) != NULL)
  1023.        *Tnormal_Ptr = Copy_Tnormal ((Default_Texture->Tnormal));
  1024.      else
  1025.        *Tnormal_Ptr = Create_Tnormal ();
  1026.  
  1027.    Parse_Pattern((TPATTERN *)*Tnormal_Ptr,NORMAL_TYPE);
  1028.   }
  1029.  
  1030.  
  1031.  
  1032. /*****************************************************************************
  1033. *
  1034. * FUNCTION
  1035. *
  1036. * INPUT
  1037. *
  1038. * OUTPUT
  1039. *
  1040. * RETURNS
  1041. *
  1042. * AUTHOR
  1043. *
  1044. *   POV-Ray Team
  1045. *   
  1046. * DESCRIPTION
  1047. *
  1048. * CHANGES
  1049. *
  1050. ******************************************************************************/
  1051.  
  1052. void Parse_Finish (Finish_Ptr)
  1053.   FINISH **Finish_Ptr;
  1054.   {
  1055.    COLOUR Temp_Colour;
  1056.    FINISH *New;
  1057.    VECTOR Local_Vector;
  1058.  
  1059.    Parse_Begin ();
  1060.  
  1061.    EXPECT        /* Look for zero or one finish_id */
  1062.      CASE (FINISH_ID_TOKEN)
  1063.        Destroy_Finish(*Finish_Ptr);
  1064.        *Finish_Ptr = Copy_Finish ((FINISH *) Token.Constant_Data);
  1065.        EXIT
  1066.      END_CASE
  1067.  
  1068.      OTHERWISE
  1069.        UNGET
  1070.        EXIT
  1071.      END_CASE
  1072.    END_EXPECT    /* End finish_id */
  1073.  
  1074.    New = *Finish_Ptr;
  1075.  
  1076.    EXPECT        /* Look for zero or more finish_body */
  1077.      CASE (AMBIENT_TOKEN)
  1078.        Parse_Colour(Temp_Colour);
  1079.        New->Ambient[RED]   = Temp_Colour[RED];
  1080.        New->Ambient[GREEN] = Temp_Colour[GREEN];
  1081.        New->Ambient[BLUE]  = Temp_Colour[BLUE];
  1082.      END_CASE
  1083.  
  1084.      CASE (BRILLIANCE_TOKEN)
  1085.        New->Brilliance = Parse_Float ();
  1086.      END_CASE
  1087.  
  1088.      CASE (DIFFUSE_TOKEN)
  1089.        New->Diffuse = Parse_Float ();
  1090.      END_CASE
  1091.  
  1092.      CASE (REFLECTION_TOKEN)
  1093.        Parse_Colour(Temp_Colour);
  1094.        New->Reflection[RED]   = Temp_Colour[RED];
  1095.        New->Reflection[GREEN] = Temp_Colour[GREEN];
  1096.        New->Reflection[BLUE]  = Temp_Colour[BLUE];
  1097.      END_CASE
  1098.  
  1099.      CASE (REFRACTION_TOKEN)
  1100.        New->Refraction = Parse_Float ();
  1101.      END_CASE
  1102.  
  1103.      CASE (IOR_TOKEN)
  1104.        New->Index_Of_Refraction = Parse_Float ();
  1105.      END_CASE
  1106.  
  1107.      CASE (PHONG_TOKEN)
  1108.        New->Phong = Parse_Float ();
  1109.      END_CASE
  1110.  
  1111.      CASE (PHONG_SIZE_TOKEN)
  1112.        New->Phong_Size = Parse_Float ();
  1113.      END_CASE
  1114.  
  1115.      CASE (SPECULAR_TOKEN)
  1116.        New->Specular = Parse_Float ();
  1117.      END_CASE
  1118.  
  1119.      CASE (ROUGHNESS_TOKEN)
  1120.        New->Roughness = Parse_Float ();
  1121.        if (New->Roughness != 0.0)
  1122.        New->Roughness = 1.0/New->Roughness; /* CEY 12/92 */
  1123.        else
  1124.          Warn(0.0, "Zero roughness used.");
  1125.      END_CASE
  1126.  
  1127.      CASE (METALLIC_TOKEN)
  1128.        New->Metallic = 1.0;
  1129.        EXPECT
  1130.          CASE_FLOAT
  1131.            New->Metallic = Parse_Float();
  1132.            EXIT
  1133.          END_CASE
  1134.  
  1135.          OTHERWISE
  1136.            UNGET
  1137.            EXIT
  1138.          END_CASE
  1139.        END_EXPECT
  1140.      END_CASE
  1141.  
  1142.      CASE (CAUSTICS_TOKEN)
  1143.        New->Caustics = Parse_Float() * 45.0;
  1144.      END_CASE
  1145.  
  1146.      CASE (CRAND_TOKEN)
  1147.        New->Crand = Parse_Float();
  1148.      END_CASE
  1149.  
  1150.      CASE (IRID_TOKEN)                     /* DMF */
  1151.        Parse_Begin();
  1152.        New->Irid = Parse_Float();
  1153.  
  1154.        EXPECT
  1155.          CASE (THICKNESS_TOKEN)           /* DMF */
  1156.            New->Irid_Film_Thickness = Parse_Float();
  1157.          END_CASE
  1158.  
  1159.          CASE (TURBULENCE_TOKEN)                /* DMF */
  1160.            Parse_Vector_Float(Local_Vector);
  1161.            New->Irid_Turb = Local_Vector[X];
  1162.          END_CASE
  1163.  
  1164.          OTHERWISE
  1165.            UNGET
  1166.            EXIT
  1167.          END_CASE
  1168.        END_EXPECT
  1169.        Parse_End();
  1170.      END_CASE
  1171.  
  1172.      CASE (FADE_DISTANCE_TOKEN)
  1173.        New->Fade_Distance = Parse_Float();
  1174.      END_CASE
  1175.  
  1176.      CASE (FADE_POWER_TOKEN)
  1177.        New->Fade_Power = Parse_Float();
  1178.      END_CASE
  1179.  
  1180.      OTHERWISE
  1181.        UNGET
  1182.        EXIT
  1183.      END_CASE
  1184.    END_EXPECT    /* End of finish_body */
  1185.  
  1186.    EXPECT        /* Look for finish_mods */
  1187.  
  1188. /*   CASE none implemented
  1189.      END_CASE     */
  1190.  
  1191.      OTHERWISE
  1192.        UNGET
  1193.        EXIT
  1194.      END_CASE
  1195.    END_EXPECT    /* End of finish_mods */
  1196.  
  1197.    Parse_End ();
  1198.   }
  1199.  
  1200.  
  1201.  
  1202. /*****************************************************************************
  1203. *
  1204. * FUNCTION
  1205. *
  1206. *   Parse_Halo
  1207. *
  1208. * INPUT
  1209. *
  1210. * OUTPUT
  1211. *
  1212. * RETURNS
  1213. *
  1214. * AUTHOR
  1215. *
  1216. *   Zsolt Szalavari
  1217. *
  1218. * DESCRIPTION
  1219. *
  1220. * CHANGES
  1221. *
  1222. *   Aug 1995 : Added and modified. [DB]
  1223. *
  1224. ******************************************************************************/
  1225.  
  1226. void Parse_Halo (Halo_Ptr)
  1227. HALO **Halo_Ptr;
  1228. {
  1229.   int add_new_halo, new_color_map, i;
  1230.   SNGL *w;
  1231.   VECTOR Local_Vector;
  1232.   MATRIX Local_Matrix;
  1233.   TRANSFORM Local_Trans;
  1234.   HALO *New, *Next_Halo;
  1235.  
  1236.   add_new_halo = TRUE;
  1237.  
  1238.   new_color_map = FALSE;
  1239.  
  1240.   Next_Halo = *Halo_Ptr;
  1241.  
  1242.   Parse_Begin();
  1243.  
  1244.   /* Look for [halo_id] */
  1245.  
  1246.   EXPECT
  1247.     CASE (HALO_ID_TOKEN)
  1248.       add_new_halo = FALSE;
  1249.       EXIT
  1250.     END_CASE
  1251.  
  1252.     OTHERWISE
  1253.       UNGET
  1254.       EXIT
  1255.     END_CASE
  1256.   END_EXPECT
  1257.  
  1258.   if (add_new_halo)
  1259.   {
  1260.     if ((Default_Texture->Halo) != NULL)
  1261.     {
  1262.       New = Copy_Halo((Default_Texture->Halo));
  1263.     }
  1264.     else
  1265.     {
  1266.       New = Create_Halo();
  1267.     }
  1268.   }
  1269.   else
  1270.   {
  1271.     New = Copy_Halo((HALO *)Token.Constant_Data);
  1272.   }
  1273.  
  1274.   EXPECT
  1275.     /* Look for halo rendering type. */
  1276.  
  1277.     CASE (ATTENUATING_TOKEN)
  1278.       New->Rendering_Type = HALO_ATTENUATING;
  1279.     END_CASE
  1280.  
  1281.     CASE (EMITTING_TOKEN)
  1282.       New->Rendering_Type = HALO_EMITTING;
  1283.     END_CASE
  1284.  
  1285.     CASE (GLOWING_TOKEN)
  1286.       New->Rendering_Type = HALO_GLOWING;
  1287.     END_CASE
  1288.  
  1289.     CASE (DUST_TOKEN)
  1290.       New->Rendering_Type = HALO_DUST;
  1291.     END_CASE
  1292.  
  1293.     CASE (VOLUME_RENDERED_TOKEN)
  1294.       New->Rendering_Type = HALO_VOLUME_RENDERED;
  1295.     END_CASE
  1296.  
  1297.     CASE (VOL_WITH_LIGHT_TOKEN)
  1298.       New->Rendering_Type = HALO_VOL_REND_WITH_LIGHT;
  1299.     END_CASE
  1300.  
  1301.     /* Look for halo density function. */
  1302.  
  1303.     CASE (CONSTANT_TOKEN)
  1304.       New->Type = HALO_CONSTANT;
  1305.     END_CASE
  1306.  
  1307.     CASE (LINEAR_TOKEN)
  1308.       New->Type = HALO_LINEAR;
  1309.     END_CASE
  1310.  
  1311.     CASE (CUBIC_TOKEN)
  1312.       New->Type = HALO_CUBIC;
  1313.     END_CASE
  1314.  
  1315.     CASE (POLY_TOKEN)
  1316.       New->Type = HALO_POLY;
  1317.     END_CASE
  1318.  
  1319.     CASE (VOLUME_OBJECT_TOKEN)
  1320.       New->Type = HALO_VOLUME_OBJECT;
  1321.     END_CASE
  1322.  
  1323.     /* Look for halo mapping type. */
  1324.  
  1325.     CASE (PLANAR_MAPPING_TOKEN)
  1326.       New->Mapping_Type = HALO_PLANAR_MAP;
  1327.     END_CASE
  1328.  
  1329.     CASE (SPHERICAL_MAPPING_TOKEN)
  1330.       New->Mapping_Type = HALO_SPHERICAL_MAP;
  1331.     END_CASE
  1332.  
  1333.     CASE (CYLINDRICAL_MAPPING_TOKEN)
  1334.       New->Mapping_Type = HALO_CYLINDRICAL_MAP;
  1335.     END_CASE
  1336.  
  1337.     CASE (BOX_MAPPING_TOKEN)
  1338.       New->Mapping_Type = HALO_BOX_MAP;
  1339.     END_CASE
  1340.  
  1341.     /* Look for halo sampling stuff. */
  1342.  
  1343.     CASE (SAMPLES_TOKEN)
  1344.       New->Samples = Parse_Float();
  1345.     END_CASE
  1346.  
  1347.     CASE (AA_LEVEL_TOKEN)
  1348.       if ((New->AA_Level = (int)Parse_Float()) < 0)
  1349.       {
  1350.         Error("Illegal anti-aliasing level value in halo.\n");
  1351.       }
  1352.     END_CASE
  1353.  
  1354.     CASE (AA_THRESHOLD_TOKEN)
  1355.       New->AA_Threshold = Parse_Float();
  1356.     END_CASE
  1357.  
  1358.     CASE (JITTER_TOKEN)
  1359.       New->Jitter = Parse_Float();
  1360.     END_CASE
  1361.  
  1362.     /* Look for other identifiers. */
  1363.  
  1364.     CASE (DUST_TYPE_TOKEN)
  1365.       New->Dust_Type = (char)Parse_Float();
  1366.       if ((New->Dust_Type < 1) || (New->Dust_Type > SCATTERING_TYPES))
  1367.       {
  1368.         Warn(0.0, "Unknown halo dust type.");
  1369.       }
  1370.     END_CASE
  1371.  
  1372.     CASE (MAX_VALUE_TOKEN)
  1373.       New->Max_Value = Parse_Float();
  1374.     END_CASE
  1375.  
  1376.     CASE (EXPONENT_TOKEN)
  1377.       New->Exponent = Parse_Float();
  1378.     END_CASE
  1379.  
  1380.     CASE (ECCENTRICITY_TOKEN)
  1381.       New->Eccentricity = Parse_Float();
  1382.     END_CASE
  1383.  
  1384.     CASE (COLOUR_MAP_TOKEN)
  1385.       Destroy_Blend_Map(New->Blend_Map);
  1386.       New->Blend_Map = Parse_Colour_Map();
  1387.       new_color_map = TRUE;
  1388.     END_CASE
  1389.  
  1390.     CASE (TRANSLATE_TOKEN)
  1391.       Parse_Vector (Local_Vector);
  1392.       Compute_Translation_Transform(&Local_Trans, Local_Vector);
  1393.       Translate_One_Halo (New, &Local_Trans);
  1394.      END_CASE
  1395.  
  1396.     CASE (ROTATE_TOKEN)
  1397.       Parse_Vector (Local_Vector);
  1398.       Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  1399.       Rotate_One_Halo (New, &Local_Trans);
  1400.      END_CASE
  1401.  
  1402.     CASE (SCALE_TOKEN)
  1403.       Parse_Scale_Vector (Local_Vector);
  1404.       Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  1405.       Scale_One_Halo (New, &Local_Trans);
  1406.     END_CASE
  1407.  
  1408.      CASE (MATRIX_TOKEN)
  1409.        Parse_Matrix(Local_Matrix);
  1410.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  1411.        Transform_One_Halo (New, &Local_Trans);
  1412.      END_CASE
  1413.  
  1414.     CASE (TRANSFORM_TOKEN)
  1415.       GET(TRANSFORM_ID_TOKEN)
  1416.       Transform_One_Halo (New, (TRANSFORM *)Token.Constant_Data);
  1417.     END_CASE
  1418.  
  1419.     CASE (TURBULENCE_TOKEN)
  1420.       if (New->Turb == NULL)
  1421.       {
  1422.         New->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  1423.       }
  1424.       Parse_Vector_Float(New->Turb->Turbulence);
  1425.     END_CASE
  1426.  
  1427.     CASE (OCTAVES_TOKEN)
  1428.       if (New->Turb == NULL)
  1429.       {
  1430.         New->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  1431.       }
  1432.       New->Turb->Octaves = (int)Parse_Float();
  1433.       if(New->Turb->Octaves < 1)
  1434.         New->Turb->Octaves = 1;
  1435.       if(New->Turb->Octaves > 10)
  1436.          New->Turb->Octaves = 10;
  1437.     END_CASE
  1438.  
  1439.     CASE (OMEGA_TOKEN)
  1440.       if (New->Turb == NULL)
  1441.       {
  1442.         New->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  1443.       }
  1444.       New->Turb->Omega = Parse_Float();
  1445.     END_CASE
  1446.  
  1447.     CASE (LAMBDA_TOKEN)
  1448.       if (New->Turb == NULL)
  1449.       {
  1450.         New->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  1451.       }
  1452.       New->Turb->Lambda = Parse_Float();
  1453.     END_CASE
  1454.  
  1455.     CASE (FREQUENCY_TOKEN)
  1456.       New->Frequency = Parse_Float();
  1457.     END_CASE
  1458.  
  1459.     CASE (PHASE_TOKEN)
  1460.       New->Phase = Parse_Float();
  1461.     END_CASE
  1462.  
  1463.     OTHERWISE
  1464.       UNGET
  1465.       EXIT
  1466.     END_CASE
  1467.   END_EXPECT
  1468.  
  1469.   if (Not_In_Default && (New->Type == HALO_NO_HALO))
  1470.   {
  1471.     Warn(3.0, "Halo type unspecified.");
  1472.   }
  1473.  
  1474.   Parse_End();
  1475.  
  1476.   if (New->Blend_Map == NULL)
  1477.   {
  1478.     Error("No color map specified with halo.\n");
  1479.   }
  1480.   else
  1481.   {
  1482.     if (new_color_map)
  1483.     {
  1484.       /* Convert differential translucencies to differential opacities. */
  1485.  
  1486.       for (i = 0; i < New->Blend_Map->Number_Of_Entries; i++)
  1487.       {
  1488.         w = &(New->Blend_Map->Blend_Map_Entries[i].Vals.Colour[TRANSM]);
  1489.  
  1490.         *w = 1.0 - *w;
  1491.       }
  1492.     }
  1493.   }
  1494.  
  1495.   /* Link halo to exisiting halos. */
  1496.  
  1497. /*
  1498.   if (add_new_halo)
  1499. */
  1500.   {
  1501.     New->Next_Halo = Next_Halo;
  1502.   }
  1503.  
  1504.   *Halo_Ptr = New;
  1505. }
  1506.  
  1507.  
  1508.  
  1509. /*****************************************************************************
  1510. *
  1511. * FUNCTION
  1512. *
  1513. * INPUT
  1514. *
  1515. * OUTPUT
  1516. *
  1517. * RETURNS
  1518. *
  1519. * AUTHOR
  1520. *
  1521. *   POV-Ray Team
  1522. *
  1523. * DESCRIPTION
  1524. *
  1525. * CHANGES
  1526. *
  1527. ******************************************************************************/
  1528.  
  1529. TEXTURE *Parse_Texture ()
  1530.   {
  1531.    VECTOR Local_Vector;
  1532.    MATRIX Local_Matrix;
  1533.    TRANSFORM Local_Trans;
  1534.    TEXTURE *Texture;
  1535.    int Modified_Pnf;
  1536.  
  1537.    if (opts.Language_Version < 3.0)
  1538.    {
  1539.      return(Parse_Vers1_Texture());
  1540.    }
  1541.  
  1542.    Modified_Pnf = FALSE;
  1543.  
  1544.    EXPECT               /* First allow a texture identifier */
  1545.      CASE (TEXTURE_ID_TOKEN)
  1546.        Texture = Copy_Textures((TEXTURE *) Token.Constant_Data);
  1547.        Modified_Pnf = TRUE;
  1548.        EXIT
  1549.      END_CASE
  1550.  
  1551.      OTHERWISE
  1552.        UNGET
  1553.        Texture = Copy_Textures (Default_Texture);
  1554.        EXIT
  1555.      END_CASE
  1556.    END_EXPECT
  1557.  
  1558.    /* If the texture identifer or the default texture was a PLAIN_PATTERN
  1559.       then allow its pigment, normal or finish to be overridden by
  1560.       pigment identifier, normal identifier and finish identifiers.
  1561.       This is a consession to backwards compatibility so that
  1562.       "texture{PIGMENT_IDENTIFIER}" etc. is legal even though it should
  1563.       be "texture{pigment{PIGMENT_IDENTIFIER}}"
  1564.    */
  1565.  
  1566.    /* Look for [pnf_texture] */
  1567.    if (Texture->Type == PLAIN_PATTERN)
  1568.    {
  1569.      EXPECT   /* Look for [pnf_ids] */
  1570.        CASE (PIGMENT_ID_TOKEN)
  1571.          Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  1572.          Destroy_Pigment(Texture->Pigment);
  1573.          Texture->Pigment = Copy_Pigment ((PIGMENT *) Token.Constant_Data);
  1574.          Modified_Pnf = TRUE;
  1575.        END_CASE
  1576.  
  1577.        CASE (TNORMAL_ID_TOKEN)
  1578.          Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  1579.          Destroy_Tnormal(Texture->Tnormal);
  1580.          Texture->Tnormal = Copy_Tnormal ((TNORMAL *) Token.Constant_Data);
  1581.          Modified_Pnf = TRUE;
  1582.        END_CASE
  1583.  
  1584.        CASE (FINISH_ID_TOKEN)
  1585.          Warn_State(Token.Token_Id, FINISH_TOKEN);
  1586.          Destroy_Finish(Texture->Finish);
  1587.          Texture->Finish = Copy_Finish ((FINISH *) Token.Constant_Data);
  1588.          Modified_Pnf = TRUE;
  1589.        END_CASE
  1590.  
  1591.        CASE (HALO_ID_TOKEN)
  1592.          Warn_State(Token.Token_Id, HALO_TOKEN);
  1593.          Destroy_Halo(Texture->Halo);
  1594.          Texture->Halo = Copy_Halo ((HALO *) Token.Constant_Data);
  1595.          Modified_Pnf = TRUE;
  1596.        END_CASE
  1597.  
  1598.        OTHERWISE
  1599.          UNGET
  1600.          EXIT
  1601.        END_CASE
  1602.      END_EXPECT
  1603.  
  1604.    /* If the texture identifer or the default texture was a PLAIN_PATTERN
  1605.       then allow its pigment, normal or finish to be overridden by
  1606.       pigment, normal or finish statement.  Also allow transformations.
  1607.    */
  1608.  
  1609.      EXPECT   /* Modify previous pnf */
  1610.        CASE (PIGMENT_TOKEN)
  1611.          Parse_Begin ();
  1612.          Parse_Pigment ( &(Texture->Pigment) );
  1613.          Parse_End ();
  1614.          Modified_Pnf = TRUE;
  1615.        END_CASE
  1616.  
  1617.        CASE (TNORMAL_TOKEN)
  1618.          Parse_Begin ();
  1619.          Parse_Tnormal ( &(Texture->Tnormal) );
  1620.          Parse_End ();
  1621.          Modified_Pnf = TRUE;
  1622.        END_CASE
  1623.  
  1624.        CASE (FINISH_TOKEN)
  1625.          Parse_Finish ( &(Texture->Finish) );
  1626.          Modified_Pnf = TRUE;
  1627.        END_CASE
  1628.  
  1629.        CASE (HALO_TOKEN)
  1630.          Parse_Halo(&(Texture->Halo));
  1631.          Modified_Pnf = TRUE;
  1632.        END_CASE
  1633.  
  1634.        CASE (TRANSLATE_TOKEN)
  1635.          Parse_Vector (Local_Vector);
  1636.          Compute_Translation_Transform(&Local_Trans, Local_Vector);
  1637.          Translate_Textures (Texture, &Local_Trans);
  1638.          Modified_Pnf = TRUE;
  1639.        END_CASE
  1640.  
  1641.        CASE (ROTATE_TOKEN)
  1642.          Parse_Vector (Local_Vector);
  1643.          Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  1644.          Rotate_Textures (Texture, &Local_Trans);
  1645.          Modified_Pnf = TRUE;
  1646.        END_CASE
  1647.  
  1648.        CASE (SCALE_TOKEN)
  1649.          Parse_Scale_Vector (Local_Vector);
  1650.          Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  1651.          Scale_Textures (Texture, &Local_Trans);
  1652.          Modified_Pnf = TRUE;
  1653.        END_CASE
  1654.  
  1655.        CASE (MATRIX_TOKEN)
  1656.          Parse_Matrix(Local_Matrix);
  1657.          Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  1658.          Transform_Textures (Texture, &Local_Trans);
  1659.          Modified_Pnf = TRUE;
  1660.        END_CASE
  1661.  
  1662.        CASE (TRANSFORM_TOKEN)
  1663.          GET(TRANSFORM_ID_TOKEN)
  1664.          Transform_Textures (Texture, (TRANSFORM *)Token.Constant_Data);
  1665.          Modified_Pnf = TRUE;
  1666.        END_CASE
  1667.  
  1668.        OTHERWISE
  1669.          UNGET
  1670.          EXIT
  1671.        END_CASE
  1672.      END_EXPECT
  1673.     }
  1674.     else
  1675.     {
  1676.     /* Here it is not a PLAIN_PATTERN texture and since default textures
  1677.        must be plain then this was a texture identifier that was a special 
  1678.        texture.  Allow transforms.  The "if(!Modified_Pnf)..." below
  1679.        will always fail if we came here.  So we return after the
  1680.        transforms. */
  1681.       Parse_Texture_Transform(Texture);
  1682.     }
  1683.  
  1684.     /* If we've modified the default texture with a p,n, or f then this
  1685.        has to stay a PLAIN_PATTERN pnf texture.  We won't allow
  1686.        a texture_map or pattern.  Therefore quit now.
  1687.      */
  1688.  
  1689.     if (!Modified_Pnf)
  1690.     {
  1691.      /* At this point we've either got a texture statement that had
  1692.         no p, n or f.  Nor any texture identifier.  Basically it means 
  1693.         this is a patterned texture_map texture. */
  1694.        
  1695.        EXPECT
  1696.          CASE (TILES_TOKEN)
  1697.            Destroy_Textures (Texture);
  1698.            Texture = Parse_Tiles();
  1699.            Parse_Texture_Transform(Texture);
  1700.            EXIT
  1701.          END_CASE
  1702.  
  1703.          CASE (MATERIAL_MAP_TOKEN)
  1704.            Destroy_Textures (Texture);
  1705.            Texture = Parse_Material_Map ();
  1706.            Parse_Texture_Transform(Texture);
  1707.            EXIT
  1708.          END_CASE
  1709.  
  1710.          OTHERWISE
  1711.            UNGET;
  1712.            Destroy_Pigment(Texture->Pigment);
  1713.            Destroy_Tnormal(Texture->Tnormal);
  1714.            Destroy_Finish(Texture->Finish);
  1715.            Destroy_Halo(Texture->Halo);
  1716.            Texture->Pigment = NULL;
  1717.            Texture->Tnormal = NULL;
  1718.            Texture->Finish  = NULL;
  1719.            Texture->Halo    = NULL;
  1720.            Parse_Pattern((TPATTERN *)Texture,TEXTURE_TYPE);
  1721.            EXIT
  1722.          END_CASE
  1723.       END_EXPECT
  1724.     }
  1725.  
  1726.     return (Texture);
  1727.   }
  1728.  
  1729.  
  1730.  
  1731. /*****************************************************************************
  1732. *
  1733. * FUNCTION
  1734. *
  1735. * INPUT
  1736. *
  1737. * OUTPUT
  1738. *
  1739. * RETURNS
  1740. *
  1741. * AUTHOR
  1742. *
  1743. *   POV-Ray Team
  1744. *   
  1745. * DESCRIPTION
  1746. *
  1747. * CHANGES
  1748. *
  1749. ******************************************************************************/
  1750.  
  1751. static TEXTURE *Parse_Tiles()
  1752. {
  1753.   TEXTURE *Texture, *Local_Texture;
  1754.   BLEND_MAP_ENTRY *Entry;
  1755.  
  1756.   Parse_Begin ();
  1757.  
  1758.   Texture = Create_Texture ();
  1759.   Destroy_Pigment(Texture->Pigment);
  1760.   Destroy_Tnormal(Texture->Tnormal);
  1761.   Destroy_Finish(Texture->Finish);
  1762.   Destroy_Halo(Texture->Halo);
  1763.   Texture->Pigment = NULL;
  1764.   Texture->Tnormal = NULL;
  1765.   Texture->Finish  = NULL;
  1766.   Texture->Halo    = NULL;
  1767.   Texture->Type = CHECKER_PATTERN;
  1768.  
  1769.   Texture->Blend_Map = Create_Blend_Map();
  1770.   Texture->Blend_Map->Number_Of_Entries = 2;
  1771.   Texture->Blend_Map->Blend_Map_Entries = Entry = Create_BMap_Entries (2);
  1772.   Texture->Blend_Map->Type = TEXTURE_TYPE;
  1773.   Entry[0].Vals.Texture=NULL;
  1774.   Entry[0].value=0.0;
  1775.   Entry[0].Same=FALSE;
  1776.   Entry[1].Vals.Texture=NULL;
  1777.   Entry[1].value=1.0;
  1778.   Entry[1].Same=FALSE;
  1779.   
  1780.   /* Note first tile is 1, 2nd tile is 0 to keep compatible with old tiles */
  1781.  
  1782.   EXPECT
  1783.     CASE (TEXTURE_TOKEN)
  1784.       Parse_Begin ();
  1785.       Local_Texture = Parse_Texture ();
  1786.       Link_Textures(&(Entry[1].Vals.Texture),Local_Texture);
  1787.       Parse_End ();
  1788.     END_CASE
  1789.  
  1790.     OTHERWISE
  1791.       UNGET
  1792.       EXIT
  1793.     END_CASE
  1794.   END_EXPECT
  1795.  
  1796.   GET (TILE2_TOKEN);
  1797.  
  1798.   EXPECT
  1799.     CASE (TEXTURE_TOKEN)
  1800.       Parse_Begin ();
  1801.       Local_Texture = Parse_Texture ();
  1802.       Link_Textures(&(Entry[0].Vals.Texture),Local_Texture);
  1803.       Parse_End ();
  1804.     END_CASE
  1805.  
  1806.     OTHERWISE
  1807.       UNGET
  1808.       EXIT
  1809.     END_CASE
  1810.   END_EXPECT
  1811.  
  1812.   Parse_End ();
  1813.  
  1814.   return (Texture);
  1815. }
  1816.  
  1817.  
  1818.  
  1819. /*****************************************************************************
  1820. *
  1821. * FUNCTION
  1822. *
  1823. * INPUT
  1824. *
  1825. * OUTPUT
  1826. *
  1827. * RETURNS
  1828. *
  1829. * AUTHOR
  1830. *
  1831. *   POV-Ray Team
  1832. *   
  1833. * DESCRIPTION
  1834. *
  1835. * CHANGES
  1836. *
  1837. ******************************************************************************/
  1838.  
  1839. static TEXTURE *Parse_Material_Map()
  1840. {
  1841.   TEXTURE *Texture, *Local_Texture;
  1842.   Parse_Begin ();
  1843.  
  1844.   Texture = Create_Texture ();
  1845.   Destroy_Pigment(Texture->Pigment);
  1846.   Destroy_Tnormal(Texture->Tnormal);
  1847.   Destroy_Finish(Texture->Finish);
  1848.   Destroy_Halo(Texture->Halo);
  1849.   Texture->Pigment = NULL;
  1850.   Texture->Tnormal = NULL;
  1851.   Texture->Finish  = NULL;
  1852.   Texture->Halo    = NULL;
  1853.   Texture->Type = BITMAP_PATTERN;
  1854.  
  1855.   Texture->Vals.Image = Parse_Image(MATERIAL_FILE);
  1856.   Texture->Vals.Image->Use_Colour_Flag = FALSE;
  1857.  
  1858.   EXPECT
  1859.     CASE (ONCE_TOKEN)
  1860.       Texture->Vals.Image->Once_Flag=TRUE;
  1861.     END_CASE
  1862.  
  1863.     CASE (INTERPOLATE_TOKEN)
  1864.       Texture->Vals.Image->Interpolation_Type=(int)Parse_Float();
  1865.     END_CASE
  1866.  
  1867.     CASE (MAP_TYPE_TOKEN)
  1868.       Texture->Vals.Image->Map_Type = (int) Parse_Float ();
  1869.     END_CASE
  1870.  
  1871.     OTHERWISE
  1872.       UNGET
  1873.       EXIT
  1874.     END_CASE
  1875.   END_EXPECT
  1876.  
  1877.   GET (TEXTURE_TOKEN)                /* First material */
  1878.   Parse_Begin();
  1879.   Texture->Materials = Local_Texture = Parse_Texture ();
  1880.   Parse_End();
  1881.   Texture->Num_Of_Mats++;
  1882.  
  1883.   EXPECT                             /* Subsequent materials */
  1884.     CASE (TEXTURE_TOKEN)
  1885.       Parse_Begin();
  1886.       Local_Texture->Next_Material = Parse_Texture ();
  1887.       Parse_End();
  1888.       Local_Texture = Local_Texture->Next_Material;
  1889.       Texture->Num_Of_Mats++;
  1890.     END_CASE
  1891.  
  1892.     OTHERWISE
  1893.       UNGET
  1894.       EXIT
  1895.     END_CASE
  1896.   END_EXPECT
  1897.  
  1898.   Parse_End ();
  1899.   
  1900.   return(Texture);
  1901. }
  1902.      
  1903.  
  1904.  
  1905. /*****************************************************************************
  1906. *
  1907. * FUNCTION
  1908. *
  1909. * INPUT
  1910. *
  1911. * OUTPUT
  1912. *
  1913. * RETURNS
  1914. *
  1915. * AUTHOR
  1916. *
  1917. *   POV-Ray Team
  1918. *   
  1919. * DESCRIPTION
  1920. *
  1921. * CHANGES
  1922. *
  1923. ******************************************************************************/
  1924.  
  1925. static TEXTURE *Parse_Vers1_Texture ()
  1926. {
  1927.    VECTOR Local_Vector;
  1928.    COLOUR Local_Colour;
  1929.    MATRIX Local_Matrix;
  1930.    TRANSFORM Local_Trans;
  1931.    TURB *Local_Turb;
  1932.    TEXTURE *Texture;
  1933.    PIGMENT *Pigment;
  1934.    TNORMAL *Tnormal;
  1935.    FINISH *Finish;
  1936.  
  1937.    EXPECT                      /* Look for texture_body */
  1938.      CASE (TILES_TOKEN)
  1939.        Texture = Parse_Tiles();
  1940.        EXIT
  1941.      END_CASE
  1942.  
  1943.      CASE (MATERIAL_MAP_TOKEN)
  1944.        Texture = Parse_Material_Map ();
  1945.        EXIT
  1946.      END_CASE
  1947.  
  1948.      CASE (TEXTURE_ID_TOKEN)
  1949.        Texture = Copy_Textures((TEXTURE *) Token.Constant_Data);
  1950.        EXIT
  1951.      END_CASE
  1952.  
  1953.      OTHERWISE
  1954.        UNGET
  1955.        Texture = Copy_Textures (Default_Texture);
  1956.        EXIT
  1957.      END_CASE
  1958.    END_EXPECT
  1959.  
  1960.    /* Look for [pnf_texture] */
  1961.    if (Texture->Type == PLAIN_PATTERN)
  1962.      {
  1963.        EXPECT   /* Look for [pnf_ids] */
  1964.          CASE (PIGMENT_ID_TOKEN)
  1965.            Destroy_Pigment(Texture->Pigment);
  1966.            Texture->Pigment = Copy_Pigment ((PIGMENT *) Token.Constant_Data);
  1967.          END_CASE
  1968.  
  1969.          CASE (TNORMAL_ID_TOKEN)
  1970.            Destroy_Tnormal(Texture->Tnormal);
  1971.            Texture->Tnormal = Copy_Tnormal ((TNORMAL *) Token.Constant_Data);
  1972.          END_CASE
  1973.  
  1974.          CASE (FINISH_ID_TOKEN)
  1975.            Destroy_Finish(Texture->Finish);
  1976.            Texture->Finish = Copy_Finish ((FINISH *) Token.Constant_Data);
  1977.          END_CASE
  1978.  
  1979.          OTHERWISE
  1980.            UNGET
  1981.            EXIT
  1982.          END_CASE
  1983.        END_EXPECT
  1984.  
  1985.        Pigment = Texture->Pigment;
  1986.        Tnormal = Texture->Tnormal;
  1987.        Finish  = Texture->Finish;
  1988.   /*     Halo    = Texture->Halo;*/
  1989.  
  1990.        EXPECT
  1991.          CASE (PIGMENT_TOKEN)
  1992.            Parse_Begin ();
  1993.            Parse_Pigment ( &(Texture->Pigment) );
  1994.            Parse_End ();
  1995.          END_CASE
  1996.  
  1997.          CASE (TNORMAL_TOKEN)
  1998.            Parse_Begin ();
  1999.            Parse_Tnormal ( &(Texture->Tnormal) );
  2000.            Parse_End ();
  2001.          END_CASE
  2002.  
  2003.          CASE (FINISH_TOKEN)
  2004.            Parse_Finish ( &(Texture->Finish) );
  2005.          END_CASE
  2006.  
  2007. /***********************************************************************
  2008. PIGMENT STUFF OUTSIDE PIGMENT{}
  2009. NOTE: Do not add new keywords to this section.  Use 1.0 syntax only.
  2010. ***********************************************************************/
  2011.          CASE (AGATE_TOKEN)
  2012.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2013.            Pigment->Type = AGATE_PATTERN;
  2014.            Pigment->Vals.Agate_Turb_Scale = 1.0;
  2015.            Check_Turb(&(Pigment->Warps));   /* agate needs Octaves, Lambda etc. */
  2016.          END_CASE
  2017.  
  2018.          CASE (BOZO_TOKEN)
  2019.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2020.            Pigment->Type = BOZO_PATTERN;
  2021.          END_CASE
  2022.  
  2023.          CASE (GRANITE_TOKEN)
  2024.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2025.            Pigment->Type = GRANITE_PATTERN;
  2026.          END_CASE
  2027.  
  2028.          CASE (LEOPARD_TOKEN)
  2029.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2030.            Pigment->Type = LEOPARD_PATTERN;
  2031.          END_CASE
  2032.  
  2033.          CASE (MARBLE_TOKEN)
  2034.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2035.            Pigment->Type = MARBLE_PATTERN;
  2036.          END_CASE
  2037.  
  2038.          CASE (MANDEL_TOKEN)
  2039.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2040.            Pigment->Type = MANDEL_PATTERN;
  2041.            Pigment->Vals.Iterations = (int)Parse_Float();
  2042.          END_CASE
  2043.  
  2044.          CASE (ONION_TOKEN)
  2045.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2046.            Pigment->Type = ONION_PATTERN;
  2047.          END_CASE
  2048.  
  2049.          CASE (PATTERN1_TOKEN)
  2050.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2051.            Pigment->Type = PATTERN1_PATTERN;
  2052.          END_CASE
  2053.  
  2054.          CASE (PATTERN2_TOKEN)
  2055.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2056.            Pigment->Type = PATTERN2_PATTERN;
  2057.          END_CASE
  2058.  
  2059.          CASE (PATTERN3_TOKEN)
  2060.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2061.            Pigment->Type = PATTERN3_PATTERN;
  2062.          END_CASE
  2063.  
  2064.          CASE (SPOTTED_TOKEN)
  2065.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2066.            Pigment->Type = SPOTTED_PATTERN;
  2067.          END_CASE
  2068.  
  2069.          CASE (WOOD_TOKEN)
  2070.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2071.            Pigment->Type = WOOD_PATTERN;
  2072.          END_CASE
  2073.  
  2074.          CASE (GRADIENT_TOKEN)
  2075.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2076.            Pigment->Type = GRADIENT_PATTERN;
  2077.            Parse_Vector (Pigment->Vals.Gradient);
  2078.          END_CASE
  2079.  
  2080.          CASE_COLOUR
  2081.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2082.            Pigment->Type = PLAIN_PATTERN;
  2083.            Parse_Colour (Pigment->Colour);
  2084.          END_CASE
  2085.  
  2086.          CASE (CHECKER_TOKEN)
  2087.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2088.            Pigment->Type = CHECKER_PATTERN;
  2089.            Pigment->Frequency = 0.0;
  2090.            Destroy_Blend_Map(Pigment->Blend_Map);
  2091.            Pigment->Blend_Map = Parse_Blend_List(2,&Check_Default_Map,COLOUR_TYPE);
  2092.          END_CASE
  2093.  
  2094.          CASE (HEXAGON_TOKEN)
  2095.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2096.            Pigment->Type = HEXAGON_PATTERN;
  2097.            Pigment->Frequency = 0.0;
  2098.            Destroy_Blend_Map(Pigment->Blend_Map);
  2099.            Pigment->Blend_Map = Parse_Blend_List(3,&Hex_Default_Map,COLOUR_TYPE);
  2100.          END_CASE
  2101.  
  2102.          CASE (IMAGE_MAP_TOKEN)
  2103.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2104.            Pigment->Type = BITMAP_PATTERN;
  2105.            Pigment->Frequency = 0.0;
  2106.            Parse_Image_Map (Pigment);
  2107.          END_CASE
  2108.  
  2109.          CASE (TURBULENCE_TOKEN)
  2110.            Local_Turb=Check_Turb(&(Pigment->Warps));
  2111.            Parse_Vector_Float(Local_Turb->Turbulence);
  2112.          END_CASE
  2113.  
  2114.          CASE (COLOUR_MAP_TOKEN)
  2115.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2116.            if (Pigment->Type == CHECKER_PATTERN ||
  2117.                Pigment->Type == HEXAGON_PATTERN ||
  2118.                Pigment->Type == PLAIN_PATTERN ||
  2119.                Pigment->Type == BITMAP_PATTERN)
  2120.              Warn(1.5, "Cannot use color map with this pigment type.");
  2121.            Destroy_Blend_Map(Pigment->Blend_Map);
  2122.            Pigment->Blend_Map = Parse_Colour_Map ();
  2123.          END_CASE
  2124.  
  2125.          CASE (QUICK_COLOUR_TOKEN)
  2126.            Warn_State(Token.Token_Id, PIGMENT_TOKEN);
  2127.            Parse_Colour (Local_Colour);
  2128.            if (opts.Quality_Flags & Q_QUICKC)
  2129.            {
  2130.               Assign_Colour(Pigment->Colour,Local_Colour);
  2131.            }
  2132.          END_CASE
  2133.  
  2134.          CASE (OCTAVES_TOKEN)
  2135.            Local_Turb=Check_Turb(&(Pigment->Warps));
  2136.            Local_Turb->Octaves = (int)Parse_Float();
  2137.            if(Local_Turb->Octaves < 1)
  2138.               Local_Turb->Octaves = 1;
  2139.            if(Local_Turb->Octaves > 10)  /* Avoid DOMAIN errors */
  2140.               Local_Turb->Octaves = 10;
  2141.          END_CASE
  2142.  
  2143.          CASE (OMEGA_TOKEN)
  2144.            Local_Turb=Check_Turb(&(Pigment->Warps));
  2145.            Local_Turb->Omega = Parse_Float();
  2146.          END_CASE
  2147.  
  2148.          CASE (LAMBDA_TOKEN)
  2149.            Local_Turb=Check_Turb(&(Pigment->Warps));
  2150.            Local_Turb->Lambda = Parse_Float();
  2151.          END_CASE
  2152.  
  2153. /***********************************************************************
  2154. TNORMAL STUFF OUTSIDE NORMAL{}
  2155. NOTE: Do not add new keywords to this section.  Use 1.0 syntax only.
  2156. ***********************************************************************/
  2157.          CASE (BUMPS_TOKEN)
  2158.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2159.            ADD_TNORMAL
  2160.            Tnormal->Type = BUMPS_PATTERN;
  2161.            Tnormal->Amount = Parse_Float ();
  2162.          END_CASE
  2163.  
  2164.          CASE (BUMPY1_TOKEN)
  2165.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2166.            ADD_TNORMAL
  2167.            Tnormal->Type = BUMPY1_PATTERN;
  2168.            Tnormal->Amount = Parse_Float ();
  2169.          END_CASE
  2170.  
  2171.          CASE (BUMPY2_TOKEN)
  2172.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2173.            ADD_TNORMAL
  2174.            Tnormal->Type = BUMPY2_PATTERN;
  2175.            Tnormal->Amount = Parse_Float ();
  2176.          END_CASE
  2177.  
  2178.          CASE (BUMPY3_TOKEN)
  2179.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2180.            ADD_TNORMAL
  2181.            Tnormal->Type = BUMPY3_PATTERN;
  2182.            Tnormal->Amount = Parse_Float ();
  2183.          END_CASE
  2184.  
  2185.          CASE (DENTS_TOKEN)
  2186.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2187.            ADD_TNORMAL
  2188.            Tnormal->Type = DENTS_PATTERN;
  2189.            Tnormal->Amount = Parse_Float ();
  2190.          END_CASE
  2191.  
  2192.          CASE (RIPPLES_TOKEN)
  2193.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2194.            ADD_TNORMAL
  2195.            Tnormal->Type = RIPPLES_PATTERN;
  2196.            Tnormal->Amount = Parse_Float ();
  2197.          END_CASE
  2198.  
  2199.          CASE (WAVES_TOKEN)
  2200.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2201.            ADD_TNORMAL
  2202.            Tnormal->Type = WAVES_PATTERN;
  2203.            Tnormal->Amount = Parse_Float ();
  2204.          END_CASE
  2205.  
  2206.          CASE (WRINKLES_TOKEN)
  2207.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2208.            ADD_TNORMAL
  2209.            Tnormal->Type = WRINKLES_PATTERN;
  2210.            Tnormal->Amount = Parse_Float ();
  2211.          END_CASE
  2212.  
  2213.          CASE (BUMP_MAP_TOKEN)
  2214.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2215.            ADD_TNORMAL
  2216.            Tnormal->Type = BITMAP_PATTERN;
  2217.            Tnormal->Frequency = 0.0;
  2218.            Parse_Bump_Map (Tnormal);
  2219.          END_CASE
  2220.  
  2221.          CASE (FREQUENCY_TOKEN)
  2222.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2223.            ADD_TNORMAL
  2224.            if (!(Tnormal->Type == RIPPLES_PATTERN || Tnormal->Type == WAVES_PATTERN))
  2225.              if (opts.Language_Version >= 1.5)
  2226.                Warn(1.5, "Cannot use frequency with this normal.");
  2227.            Tnormal->Frequency = Parse_Float();
  2228.          END_CASE
  2229.  
  2230.          CASE (PHASE_TOKEN)
  2231.            Warn_State(Token.Token_Id, TNORMAL_TOKEN);
  2232.            ADD_TNORMAL
  2233.            if (!(Tnormal->Type == RIPPLES_PATTERN || Tnormal->Type == WAVES_PATTERN))
  2234.              if (opts.Language_Version >= 1.5)
  2235.                Warn(1.5, "Cannot use phase with this normal.");
  2236.            Tnormal->Phase = Parse_Float();
  2237.          END_CASE
  2238.  
  2239.  
  2240. /***********************************************************************
  2241. FINISH STUFF OUTSIDE FINISH{}
  2242. NOTE: Do not add new keywords to this section.  Use 1.0 syntax only.
  2243. ***********************************************************************/
  2244.          CASE (AMBIENT_TOKEN)
  2245.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2246.            Finish->Ambient[RED]   =
  2247.            Finish->Ambient[GREEN] =
  2248.            Finish->Ambient[BLUE]  = Parse_Float ();
  2249.          END_CASE
  2250.  
  2251.          CASE (BRILLIANCE_TOKEN)
  2252.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2253.            Finish->Brilliance = Parse_Float ();
  2254.          END_CASE
  2255.  
  2256.          CASE (DIFFUSE_TOKEN)
  2257.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2258.            Finish->Diffuse = Parse_Float ();
  2259.          END_CASE
  2260.  
  2261.          CASE (REFLECTION_TOKEN)
  2262.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2263.            Finish->Reflection[RED]   =
  2264.            Finish->Reflection[GREEN] =
  2265.            Finish->Reflection[BLUE]  = Parse_Float ();
  2266.          END_CASE
  2267.  
  2268.          CASE (REFRACTION_TOKEN)
  2269.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2270.            Finish->Refraction = Parse_Float ();
  2271.          END_CASE
  2272.  
  2273.          CASE (IOR_TOKEN)
  2274.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2275.            Finish->Index_Of_Refraction = Parse_Float ();
  2276.          END_CASE
  2277.  
  2278.          CASE (PHONG_TOKEN)
  2279.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2280.            Finish->Phong = Parse_Float ();
  2281.          END_CASE
  2282.  
  2283.          CASE (PHONG_SIZE_TOKEN)
  2284.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2285.            Finish->Phong_Size = Parse_Float ();
  2286.          END_CASE
  2287.  
  2288.          CASE (SPECULAR_TOKEN)
  2289.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2290.            Finish->Specular = Parse_Float ();
  2291.          END_CASE
  2292.  
  2293.          CASE (ROUGHNESS_TOKEN)
  2294.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2295.            Finish->Roughness = Parse_Float ();
  2296.            if (Finish->Roughness != 0.0)
  2297.            Finish->Roughness = 1.0/Finish->Roughness; /* CEY 12/92 */
  2298.            else
  2299.              Warn(0.0, "Zero roughness used.");
  2300.          END_CASE
  2301.  
  2302.          CASE (METALLIC_TOKEN)
  2303.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2304.            Finish->Metallic = 1.0;
  2305.          END_CASE
  2306.  
  2307.          CASE (CRAND_TOKEN)
  2308.            Warn_State(Token.Token_Id, FINISH_TOKEN);
  2309.            Finish->Crand = Parse_Float();
  2310.          END_CASE
  2311.  
  2312.          CASE_FLOAT
  2313.            Finish->Crand = Parse_Float();
  2314.            Warn(1.5, "Should use crand keyword in finish statement.");
  2315.          END_CASE
  2316.  
  2317.          CASE (TRANSLATE_TOKEN)
  2318.            Parse_Vector (Local_Vector);
  2319.            Compute_Translation_Transform(&Local_Trans, Local_Vector);
  2320.            Translate_Textures (Texture, &Local_Trans);
  2321.          END_CASE
  2322.  
  2323.          CASE (ROTATE_TOKEN)
  2324.            Parse_Vector (Local_Vector);
  2325.            Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  2326.            Rotate_Textures (Texture, &Local_Trans);
  2327.          END_CASE
  2328.  
  2329.          CASE (SCALE_TOKEN)
  2330.            Parse_Scale_Vector (Local_Vector);
  2331.            Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  2332.            Scale_Textures (Texture, &Local_Trans);
  2333.          END_CASE
  2334.  
  2335.          CASE (MATRIX_TOKEN)
  2336.            Parse_Matrix(Local_Matrix);
  2337.            Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  2338.            Transform_Textures (Texture, &Local_Trans);
  2339.          END_CASE
  2340.  
  2341.          CASE (TRANSFORM_TOKEN)
  2342.            GET(TRANSFORM_ID_TOKEN)
  2343.            Transform_Textures (Texture, (TRANSFORM *)Token.Constant_Data);
  2344.          END_CASE
  2345.  
  2346.          CASE (TEXTURE_ID_TOKEN)
  2347.            Warn(0.0, "Texture identifier overwriting previous values.");
  2348.            Destroy_Textures(Texture);
  2349.            Texture = Copy_Textures((TEXTURE *) Token.Constant_Data);
  2350.            Pigment = Texture->Pigment;
  2351.            Tnormal = Texture->Tnormal;
  2352.            Finish  = Texture->Finish;
  2353.   /*         Halo    = Texture->Halo;*/
  2354.          END_CASE
  2355.  
  2356.          OTHERWISE
  2357.            UNGET
  2358.            EXIT
  2359.          END_CASE
  2360. /***********************************************************************/
  2361.  
  2362.        END_EXPECT
  2363.  
  2364.        if (Not_In_Default && (Texture->Pigment->Type == NO_PATTERN) &&
  2365.            !(opts.Language_Version < 1.5))
  2366.          Parse_Error(PIGMENT_ID_TOKEN);
  2367.  
  2368.      }
  2369.  
  2370.    Parse_Texture_Transform(Texture);
  2371.  
  2372.    return (Texture);
  2373.   }
  2374.  
  2375.  
  2376.  
  2377. /*****************************************************************************
  2378. *
  2379. * FUNCTION
  2380. *
  2381. * INPUT
  2382. *
  2383. * OUTPUT
  2384. *
  2385. * RETURNS
  2386. *
  2387. * AUTHOR
  2388. *
  2389. *   POV-Ray Team
  2390. *   
  2391. * DESCRIPTION
  2392. *
  2393. * CHANGES
  2394. *
  2395. ******************************************************************************/
  2396.  
  2397. static void Parse_Texture_Transform (Texture)
  2398. TEXTURE *Texture;
  2399. {
  2400.    VECTOR Local_Vector;
  2401.    MATRIX Local_Matrix;
  2402.    TRANSFORM Local_Trans;
  2403.  
  2404.    EXPECT
  2405.      CASE (TRANSLATE_TOKEN)
  2406.        Parse_Vector (Local_Vector);
  2407.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  2408.        Translate_Textures (Texture, &Local_Trans);
  2409.      END_CASE
  2410.  
  2411.      CASE (ROTATE_TOKEN)
  2412.        Parse_Vector (Local_Vector);
  2413.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  2414.        Rotate_Textures (Texture, &Local_Trans);
  2415.      END_CASE
  2416.  
  2417.      CASE (SCALE_TOKEN)
  2418.        Parse_Scale_Vector (Local_Vector);
  2419.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  2420.        Scale_Textures (Texture, &Local_Trans);
  2421.      END_CASE
  2422.  
  2423.      CASE (MATRIX_TOKEN)
  2424.        Parse_Matrix(Local_Matrix);
  2425.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  2426.        Transform_Textures (Texture, &Local_Trans);
  2427.      END_CASE
  2428.  
  2429.      CASE (TRANSFORM_TOKEN)
  2430.        GET(TRANSFORM_ID_TOKEN)
  2431.        Transform_Textures (Texture, (TRANSFORM *)Token.Constant_Data);
  2432.      END_CASE
  2433.  
  2434.      OTHERWISE
  2435.        UNGET
  2436.        EXIT
  2437.      END_CASE
  2438.    END_EXPECT
  2439. }
  2440.  
  2441.  
  2442. /*****************************************************************************
  2443. *
  2444. * FUNCTION
  2445. *
  2446. *   Parse_Atmosphere
  2447. *
  2448. * INPUT
  2449. *
  2450. * OUTPUT
  2451. *   
  2452. * RETURNS
  2453. *   
  2454. * AUTHOR
  2455. *
  2456. *   Dieter Bayer
  2457. *   
  2458. * DESCRIPTION
  2459. *
  2460. *   -
  2461. *
  2462. * CHANGES
  2463. *
  2464. *   Nov 1994 : Creation.
  2465. *
  2466. ******************************************************************************/
  2467.  
  2468. ATMOSPHERE *Parse_Atmosphere()
  2469. {
  2470.   ATMOSPHERE *Atmosphere;
  2471.  
  2472.   Parse_Begin();
  2473.  
  2474.   EXPECT
  2475.     CASE(ATMOSPHERE_ID_TOKEN)
  2476.       Atmosphere = Copy_Atmosphere((ATMOSPHERE *)Token.Constant_Data);
  2477.       EXIT
  2478.     END_CASE
  2479.  
  2480.     OTHERWISE
  2481.       UNGET
  2482.         Atmosphere = Create_Atmosphere();
  2483.       EXIT
  2484.     END_CASE
  2485.   END_EXPECT
  2486.  
  2487.   EXPECT
  2488.     CASE (TYPE_TOKEN)
  2489.       Atmosphere->Type = (int)Parse_Float();
  2490.       if ((Atmosphere->Type < 1) || (Atmosphere->Type > SCATTERING_TYPES))
  2491.       {
  2492.         Warn(0.0, "Unknown atmospheric scattering type.");
  2493.       }
  2494.     END_CASE
  2495.  
  2496.     CASE (DISTANCE_TOKEN)
  2497.       Atmosphere->Distance = Parse_Float();
  2498.     END_CASE
  2499.  
  2500.     CASE (SAMPLES_TOKEN)
  2501.       if ((Atmosphere->Samples = (int)Parse_Float()) < 1)
  2502.       {
  2503.         Error("Illegal samples value in atmosphere.\n");
  2504.       }
  2505.     END_CASE
  2506.  
  2507.     CASE (SCATTERING_TOKEN)
  2508.       Atmosphere->Scattering = Parse_Float();
  2509.     END_CASE
  2510.  
  2511.     CASE (AA_LEVEL_TOKEN)
  2512.       if ((Atmosphere->AA_Level = (int)Parse_Float()) < 0)
  2513.       {
  2514.         Error("Illegal level value in atmosphere.\n");
  2515.       }
  2516.     END_CASE
  2517.  
  2518.     CASE (AA_THRESHOLD_TOKEN)
  2519.       Atmosphere->AA_Threshold = Parse_Float();
  2520.     END_CASE
  2521.  
  2522.     CASE (JITTER_TOKEN)
  2523.       Atmosphere->Jitter = Parse_Float();
  2524.     END_CASE
  2525.  
  2526.     CASE (ECCENTRICITY_TOKEN)
  2527.       Atmosphere->Eccentricity = Parse_Float();
  2528.     END_CASE
  2529.  
  2530.     CASE_COLOUR
  2531.       Parse_Colour(Atmosphere->Colour);
  2532.     END_CASE
  2533.  
  2534.     OTHERWISE
  2535.       UNGET
  2536.       EXIT
  2537.     END_CASE
  2538.   END_EXPECT
  2539.  
  2540.   Parse_End();
  2541.  
  2542.   return(Atmosphere);
  2543. }
  2544.  
  2545.  
  2546.  
  2547. /*****************************************************************************
  2548. *
  2549. * FUNCTION
  2550. *
  2551. * INPUT
  2552. *
  2553. * OUTPUT
  2554. *
  2555. * RETURNS
  2556. *
  2557. * AUTHOR
  2558. *
  2559. *   POV-Ray Team
  2560. *
  2561. * DESCRIPTION
  2562. *
  2563. * CHANGES
  2564. *
  2565. ******************************************************************************/
  2566.  
  2567. FOG *Parse_Fog()
  2568. {
  2569.   VECTOR Vector;
  2570.   MATRIX Matrix;
  2571.   TRANSFORM Trans;
  2572.   FOG *Fog;
  2573.  
  2574.   Parse_Begin();
  2575.  
  2576.   EXPECT
  2577.     CASE(FOG_ID_TOKEN)
  2578.       Fog = Copy_Fog ((FOG *) Token.Constant_Data);
  2579.       EXIT
  2580.     END_CASE
  2581.  
  2582.     OTHERWISE
  2583.       UNGET
  2584.       Fog = Create_Fog();
  2585.       EXIT
  2586.     END_CASE
  2587.   END_EXPECT
  2588.  
  2589.   EXPECT
  2590.     CASE_COLOUR
  2591.       Parse_Colour(Fog->Colour);
  2592.     END_CASE
  2593.  
  2594.     CASE (DISTANCE_TOKEN)
  2595.       Fog->Distance = Parse_Float();
  2596.     END_CASE
  2597.  
  2598.     CASE_FLOAT
  2599.       Warn(1.5, "Should use distance keyword.");
  2600.       Fog->Distance = Parse_Float();
  2601.     END_CASE
  2602.  
  2603.     CASE (FOG_TYPE_TOKEN)
  2604.       Fog->Type = (int)Parse_Float();
  2605.       if ((Fog->Type < ORIG_FOG) || (Fog->Type > FOG_TYPES))
  2606.       {
  2607.         Warn(0.0, "Unknown fog type.");
  2608.       }
  2609.     END_CASE
  2610.  
  2611.     CASE (FOG_ALT_TOKEN)
  2612.       Fog->Alt = Parse_Float();
  2613.     END_CASE
  2614.  
  2615.     CASE (FOG_OFFSET_TOKEN)
  2616.       Fog->Offset = Parse_Float();
  2617.     END_CASE
  2618.  
  2619.     CASE (TURB_DEPTH_TOKEN)
  2620.       Fog->Turb_Depth = Parse_Float();
  2621.     END_CASE
  2622.  
  2623.     CASE (UP_TOKEN)
  2624.       Parse_Vector(Fog->Up);
  2625.     END_CASE
  2626.  
  2627.     CASE (TURBULENCE_TOKEN)
  2628.       if (Fog->Turb == NULL)
  2629.       {
  2630.         Fog->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  2631.       }
  2632.       Parse_Vector_Float(Fog->Turb->Turbulence);
  2633.     END_CASE
  2634.  
  2635.     CASE (OCTAVES_TOKEN)
  2636.       if (Fog->Turb == NULL)
  2637.       {
  2638.         Fog->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  2639.       }
  2640.       Fog->Turb->Octaves = (int)Parse_Float();
  2641.       if(Fog->Turb->Octaves < 1)
  2642.         Fog->Turb->Octaves = 1;
  2643.       if(Fog->Turb->Octaves > 10)
  2644.          Fog->Turb->Octaves = 10;
  2645.     END_CASE
  2646.  
  2647.     CASE (OMEGA_TOKEN)
  2648.       if (Fog->Turb == NULL)
  2649.       {
  2650.         Fog->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  2651.       }
  2652.       Fog->Turb->Omega = Parse_Float();
  2653.     END_CASE
  2654.  
  2655.     CASE (LAMBDA_TOKEN)
  2656.       if (Fog->Turb == NULL)
  2657.       {
  2658.         Fog->Turb=(TURB *)Create_Warp(CLASSIC_TURB_WARP);
  2659.       }
  2660.       Fog->Turb->Lambda = Parse_Float();
  2661.     END_CASE
  2662.  
  2663.     CASE (ROTATE_TOKEN)
  2664.       Parse_Vector(Vector);
  2665.       Compute_Rotation_Transform(&Trans, Vector);
  2666.       MTransDirection(Fog->Up, Fog->Up, &Trans);
  2667.     END_CASE
  2668.  
  2669.     CASE (SCALE_TOKEN)
  2670.       Parse_Vector(Vector);
  2671.       Compute_Scaling_Transform(&Trans, Vector);
  2672.       MTransDirection(Fog->Up, Fog->Up, &Trans);
  2673.     END_CASE
  2674.  
  2675.     CASE (TRANSLATE_TOKEN)
  2676.       Parse_Vector(Vector);
  2677.       Warn(0.0, "A fog's up vector can't be translated.");
  2678. /*
  2679.       Compute_Translation_Transform(&Trans, Vector);
  2680.       MTransDirection(Fog->Up, Fog->Up, &Trans);
  2681. */
  2682.     END_CASE
  2683.  
  2684.     CASE (MATRIX_TOKEN)
  2685.       Parse_Matrix(Matrix);
  2686.       Compute_Matrix_Transform(&Trans, Matrix);
  2687.       MTransDirection(Fog->Up, Fog->Up, &Trans);
  2688.     END_CASE
  2689.  
  2690.     CASE (TRANSFORM_TOKEN)
  2691.       GET(TRANSFORM_ID_TOKEN)
  2692.       MTransDirection(Fog->Up, Fog->Up, (TRANSFORM *)Token.Constant_Data);
  2693.     END_CASE
  2694.  
  2695.     OTHERWISE
  2696.       UNGET
  2697.       EXIT
  2698.     END_CASE
  2699.   END_EXPECT
  2700.  
  2701.   Parse_End ();
  2702.  
  2703.   /* Make sure the up vector is normalized. */
  2704.  
  2705.   VNormalize(Fog->Up, Fog->Up);
  2706.  
  2707.   return(Fog);
  2708. }
  2709.  
  2710.  
  2711.  
  2712. /*****************************************************************************
  2713. *
  2714. * FUNCTION
  2715. *
  2716. *   Parse_Rainbow
  2717. *
  2718. * INPUT
  2719. *   
  2720. * OUTPUT
  2721. *   
  2722. * RETURNS
  2723. *   
  2724. * AUTHOR
  2725. *
  2726. *   Dieter Bayer
  2727. *   
  2728. * DESCRIPTION
  2729. *
  2730. *   -
  2731. *
  2732. * CHANGES
  2733. *
  2734. *   Jul 1994 : Creation.
  2735. *
  2736. *   Dec 1994 : Modified to work with multiple rainbows. [DB]
  2737. *
  2738. *   Apr 1995 : Added code for rainbow arcs. [DB]
  2739. *
  2740. ******************************************************************************/
  2741.  
  2742. RAINBOW *Parse_Rainbow()
  2743. {
  2744.   int Angle1, Angle2;
  2745.   DBL dot;
  2746.   RAINBOW *Rainbow;
  2747.  
  2748.   Angle1 = Angle2 = FALSE;
  2749.  
  2750.   Parse_Begin();
  2751.  
  2752.   EXPECT
  2753.     CASE(RAINBOW_ID_TOKEN)
  2754.       Rainbow = Copy_Rainbow ((RAINBOW *) Token.Constant_Data);
  2755.       EXIT
  2756.     END_CASE
  2757.  
  2758.     OTHERWISE
  2759.       UNGET
  2760.       Rainbow = Create_Rainbow();
  2761.       EXIT
  2762.     END_CASE
  2763.   END_EXPECT
  2764.  
  2765.   EXPECT
  2766.     CASE (ANGLE_TOKEN)
  2767.       Rainbow->Angle = Parse_Float();
  2768.     END_CASE
  2769.  
  2770.     CASE (DIRECTION_TOKEN)
  2771.       Parse_Vector(Rainbow->Antisolar_Vector);
  2772.     END_CASE
  2773.  
  2774.     CASE (COLOUR_MAP_TOKEN)
  2775.       Rainbow->Pigment = Create_Pigment();
  2776.       Rainbow->Pigment->Blend_Map = Parse_Colour_Map();
  2777.       Rainbow->Pigment->Type = GRADIENT_PATTERN;
  2778.       Make_Vector (Rainbow->Pigment->Vals.Gradient,1.0,0.0,0.0);
  2779.     END_CASE
  2780.  
  2781.     CASE (DISTANCE_TOKEN)
  2782.       Rainbow->Distance = Parse_Float();
  2783.     END_CASE
  2784.  
  2785.     CASE (JITTER_TOKEN)
  2786.       Rainbow->Jitter = Parse_Float();
  2787.     END_CASE
  2788.  
  2789.     CASE (WIDTH_TOKEN)
  2790.       Rainbow->Width = Parse_Float();
  2791.     END_CASE
  2792.  
  2793.     CASE (UP_TOKEN)
  2794.       Parse_Vector(Rainbow->Up_Vector);
  2795.     END_CASE
  2796.  
  2797.     CASE (FALLOFF_ANGLE_TOKEN)
  2798.       Angle1 = TRUE;
  2799.       Rainbow->Falloff_Angle = Parse_Float();
  2800.       if ((Rainbow->Falloff_Angle < 0.0) || (Rainbow->Falloff_Angle > 360.0))
  2801.       {
  2802.         Error("Illegal falloff angle in rainbow (Use value from 0 to 360 degrees).\n");
  2803.       }
  2804.       Rainbow->Falloff_Angle *= M_PI / 360.0;
  2805.     END_CASE
  2806.  
  2807.     CASE (ARC_ANGLE_TOKEN)
  2808.       Angle2 = TRUE;
  2809.       Rainbow->Arc_Angle = Parse_Float();
  2810.       if ((Rainbow->Arc_Angle < 0.0) || (Rainbow->Arc_Angle > 360.0))
  2811.       {
  2812.         Error("Illegal arc angle in rainbow (Use value from 0 to 360 degrees).\n");
  2813.       }
  2814.       Rainbow->Arc_Angle *= M_PI / 360.0;
  2815.     END_CASE
  2816.  
  2817.     OTHERWISE
  2818.       UNGET
  2819.       EXIT
  2820.     END_CASE
  2821.   END_EXPECT
  2822.  
  2823.   Parse_End();
  2824.  
  2825.   /* Setup falloff angle. */
  2826.  
  2827.   if (Angle2 && !Angle1)
  2828.   {
  2829.     Rainbow->Falloff_Angle = Rainbow->Arc_Angle;
  2830.   }
  2831.  
  2832.   /* Test if arc angle is greater or equal to falloff angle. */
  2833.  
  2834.   if (Rainbow->Arc_Angle < Rainbow->Falloff_Angle)
  2835.   {
  2836.     Error("Arc angle is smaller than falloff angle in rainbow.\n");
  2837.   }
  2838.  
  2839.   /* Get falloff region width.*/
  2840.  
  2841.   Rainbow->Falloff_Width = Rainbow->Arc_Angle - Rainbow->Falloff_Angle;
  2842.  
  2843.   /* Check for illegal vectors. */
  2844.  
  2845.   VDot(dot, Rainbow->Antisolar_Vector, Rainbow->Antisolar_Vector);
  2846.  
  2847.   if (fabs(dot) < EPSILON)
  2848.   {
  2849.     Error("Rainbow's direction vector is zero.\n");
  2850.   }
  2851.  
  2852.   VDot(dot, Rainbow->Up_Vector, Rainbow->Up_Vector);
  2853.  
  2854.   if (fabs(dot) < EPSILON)
  2855.   {
  2856.     Error("Rainbow's up vector is zero.\n");
  2857.   }
  2858.  
  2859.   VNormalizeEq(Rainbow->Antisolar_Vector);
  2860.   VNormalizeEq(Rainbow->Up_Vector);
  2861.  
  2862.   VDot(dot, Rainbow->Up_Vector, Rainbow->Antisolar_Vector);
  2863.  
  2864.   if (fabs(1.0 - fabs(dot)) < EPSILON)
  2865.   {
  2866.     Error("Rainbow's up and direction vector are co-linear.\n");
  2867.   }
  2868.  
  2869.   /* Make sure that up and antisolar vector are perpendicular. */
  2870.  
  2871.   VCross(Rainbow->Right_Vector, Rainbow->Up_Vector, Rainbow->Antisolar_Vector);
  2872.  
  2873.   VCross(Rainbow->Up_Vector, Rainbow->Antisolar_Vector, Rainbow->Right_Vector);
  2874.  
  2875.   VNormalizeEq(Rainbow->Up_Vector);
  2876.   VNormalizeEq(Rainbow->Right_Vector);
  2877.  
  2878.   /* Adjust rainbow angle and width. */
  2879.  
  2880.   Rainbow->Angle -= 0.5 * Rainbow->Width;
  2881.  
  2882.   Rainbow->Angle *= M_PI / 180.0;
  2883.   Rainbow->Width *= M_PI / 180.0;
  2884.  
  2885.   return(Rainbow);
  2886. }
  2887.  
  2888.  
  2889.  
  2890. /*****************************************************************************
  2891. *
  2892. * FUNCTION
  2893. *
  2894. *   Parse_Skysphere
  2895. *
  2896. * INPUT
  2897. *   
  2898. * OUTPUT
  2899. *   
  2900. * RETURNS
  2901. *   
  2902. * AUTHOR
  2903. *
  2904. *   Dieter Bayer
  2905. *   
  2906. * DESCRIPTION
  2907. *
  2908. *   -
  2909. *
  2910. * CHANGES
  2911. *
  2912. *   Jul 1994 : Creation.
  2913. *
  2914. *   Dec 1994 : Modified to work with multiple skyspheres. [DB]
  2915. *
  2916. ******************************************************************************/
  2917.  
  2918. SKYSPHERE *Parse_Skysphere()
  2919. {
  2920.   VECTOR Local_Vector;
  2921.   MATRIX Local_Matrix;
  2922.   TRANSFORM Local_Trans;
  2923.   SKYSPHERE *Skysphere;
  2924.  
  2925.   Parse_Begin();
  2926.  
  2927.   EXPECT
  2928.     CASE(SKYSPHERE_ID_TOKEN)
  2929.       Skysphere = Copy_Skysphere((SKYSPHERE *)Token.Constant_Data);
  2930.       EXIT
  2931.     END_CASE
  2932.  
  2933.     OTHERWISE
  2934.       UNGET
  2935.       Skysphere = Create_Skysphere();
  2936.       EXIT
  2937.     END_CASE
  2938.   END_EXPECT
  2939.  
  2940.   EXPECT
  2941.     CASE (PIGMENT_TOKEN)
  2942.       Skysphere->Count++;
  2943.       Skysphere->Pigments = POV_REALLOC(Skysphere->Pigments, Skysphere->Count*sizeof(SKYSPHERE *), "sky-sphere pigment");
  2944.       Skysphere->Pigments[Skysphere->Count-1] = Create_Pigment();
  2945.       Parse_Begin();
  2946.       Parse_Pigment(&(Skysphere->Pigments[Skysphere->Count-1]));
  2947.       Parse_End();
  2948.     END_CASE
  2949.  
  2950.     CASE (TRANSLATE_TOKEN)
  2951.       Parse_Vector (Local_Vector);
  2952.       Translate_Skysphere(Skysphere, Local_Vector);
  2953.     END_CASE
  2954.  
  2955.     CASE (ROTATE_TOKEN)
  2956.       Parse_Vector (Local_Vector);
  2957.       Rotate_Skysphere(Skysphere, Local_Vector);
  2958.     END_CASE
  2959.  
  2960.     CASE (SCALE_TOKEN)
  2961.       Parse_Scale_Vector (Local_Vector);
  2962.       Scale_Skysphere(Skysphere, Local_Vector);
  2963.     END_CASE
  2964.  
  2965.     CASE (MATRIX_TOKEN)
  2966.       Parse_Matrix(Local_Matrix);
  2967.       Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  2968.       Transform_Skysphere(Skysphere, &Local_Trans);
  2969.     END_CASE
  2970.  
  2971.     CASE (TRANSFORM_TOKEN)
  2972.       GET(TRANSFORM_ID_TOKEN)
  2973.       Transform_Skysphere(Skysphere, (TRANSFORM *)Token.Constant_Data);
  2974.     END_CASE
  2975.  
  2976.     OTHERWISE
  2977.       UNGET
  2978.       EXIT
  2979.     END_CASE
  2980.   END_EXPECT
  2981.  
  2982.   Parse_End();
  2983.   
  2984.   if (Skysphere->Count==0)
  2985.   {
  2986.     Error("Empty sky_sphere statement.");
  2987.   }
  2988.  
  2989.   return(Skysphere);
  2990. }
  2991.  
  2992. /*****************************************************************************
  2993. *
  2994. * FUNCTION      : Check_BH_Parameters
  2995. *
  2996. * ARGUMENTS     : bh - pointer to Black_Hole
  2997. *
  2998. * AUTHOR        : CJC [7/95]
  2999. *
  3000. * DESCRIPTION   : Applies sanity checks to the parameters of a black hole.
  3001. *
  3002. * CHANGES
  3003. *
  3004. ******************************************************************************/
  3005.  
  3006. static void Check_BH_Parameters (bh)
  3007. BLACK_HOLE *bh;
  3008. {
  3009.   if (bh->Repeat == FALSE) return ;
  3010.  
  3011.   if (bh->Repeat_Vector [X] > 0.0)
  3012.   {
  3013.     if (bh->Center [X] < bh->Radius)
  3014.       bh->Center [X] = bh->Radius ;
  3015.     if (bh->Repeat_Vector [X] < bh->Center [X] + bh->Radius + bh->Uncertainty_Vector [X])
  3016.     {
  3017.       bh->Repeat_Vector [X] = bh->Center [X] + bh->Radius + bh->Uncertainty_Vector [X] ;
  3018.       Warning (0.0, "Black Hole repeat vector X too small ; increased to %g\n", bh->Repeat_Vector [X]) ;
  3019.     } 
  3020.     if (bh->Repeat_Vector [X] < Small_Tolerance)
  3021.     {
  3022.       Warning (0.0,"Black Hole repeat vector X is less than %f ; ignored\n", (float) Small_Tolerance) ;
  3023.       bh->Repeat_Vector [X] = 0.0 ;
  3024.     }
  3025.   }
  3026.  
  3027.   if (bh->Repeat_Vector [Y] > 0.0)
  3028.   {
  3029.     if (bh->Center [Y] < bh->Radius)
  3030.       bh->Center [Y] = bh->Radius ;
  3031.     if (bh->Repeat_Vector [Y] < bh->Center [Y] + bh->Radius + bh->Uncertainty_Vector [Y])
  3032.     {
  3033.       bh->Repeat_Vector [Y] = bh->Center [Y] + bh->Radius + bh->Uncertainty_Vector [Y] ;
  3034.       Warning (0.0, "Black Hole repeat vector Y too small ; increased to %g\n", bh->Repeat_Vector [Y]) ;
  3035.     } 
  3036.     if (bh->Repeat_Vector [Y] < Small_Tolerance)
  3037.     {
  3038.       Warning (0.0, "Black Hole repeat vector Y is less than %f ; ignored\n", (float) Small_Tolerance) ;
  3039.       bh->Repeat_Vector [Y] = 0.0 ;
  3040.     } 
  3041.   }
  3042.  
  3043.   if (bh->Repeat_Vector [Z] > 0.0)
  3044.   {
  3045.     if (bh->Center [Z] < bh->Radius)
  3046.       bh->Center [Z] = bh->Radius ;
  3047.     if (bh->Repeat_Vector [Z] < bh->Center [Z] + bh->Radius + bh->Uncertainty_Vector [Z])
  3048.     {
  3049.       bh->Repeat_Vector [Z] = bh->Center [Z] + bh->Radius + bh->Uncertainty_Vector [Z] ;
  3050.       Warning (0.0, "Black Hole repeat vector Z too small ; increased to %g\n", bh->Repeat_Vector [Z]) ;
  3051.     } 
  3052.     if (bh->Repeat_Vector [Z] < Small_Tolerance)
  3053.     {
  3054.       Warning (0.0, "Black Hole repeat vector Z is less than %f ; ignored\n", (float) Small_Tolerance) ;
  3055.       bh->Repeat_Vector [Z] = 0.0 ;
  3056.     }
  3057.   }
  3058. }
  3059.  
  3060. /*****************************************************************************
  3061. *
  3062. * FUNCTION
  3063. *
  3064. *   Check_Turb
  3065. *
  3066. * INPUT
  3067. *
  3068. *   Warps_Ptr : Address where the root warp of a warp list
  3069. *   is stored.
  3070. *   
  3071. * OUTPUT
  3072. *
  3073. *   Warps_Ptr : If *Warps_Ptr is NULL, a classic turb warp
  3074. *   is created and a pointer to it is stored
  3075. *   
  3076. * RETURNS
  3077. *
  3078. *   A pointer to the last warp in the chain which is guarenteed
  3079. *   to be a classic turb.
  3080. *   
  3081. * AUTHOR
  3082. *
  3083. *   CEY [2/95]
  3084. *   
  3085. * DESCRIPTION   : This routine is called when a classic outside-the-warp
  3086. *  turbulence parameter is parsed.  One and only one classic turb may exist 
  3087. *  in a warp chain.  If there is one, it must be the last.  This routine 
  3088. *  traverses the warp chain and looks at the last link.  If it is not a 
  3089. *  classic turb then it adds one to the end and returns a pointer to it.
  3090. *  If the chain is empty, it creates a single link chain consisting of a 
  3091. *  classic turb link.  Future warp links get added ahead of the chain so
  3092. *  that any classic turb link is always last.
  3093. *
  3094. * CHANGES
  3095. *
  3096. ******************************************************************************/
  3097.  
  3098. static TURB *Check_Turb (Warps_Ptr)
  3099. WARP **Warps_Ptr;
  3100. {
  3101.   WARP *Temp=*Warps_Ptr;
  3102.   
  3103.   if (Temp == NULL)
  3104.   {
  3105.     *Warps_Ptr = Temp = Create_Warp(CLASSIC_TURB_WARP);
  3106.   }
  3107.   else
  3108.   {
  3109.     while (Temp->Next_Warp != NULL)
  3110.     {
  3111.       Temp=Temp->Next_Warp;
  3112.     }
  3113.   
  3114.     if (Temp->Warp_Type != CLASSIC_TURB_WARP)
  3115.     {
  3116.       Temp->Next_Warp=Create_Warp(CLASSIC_TURB_WARP);
  3117.       Temp=Temp->Next_Warp;
  3118.     }
  3119.   }
  3120.   return((TURB *)Temp);
  3121. }
  3122.  
  3123.  
  3124.  
  3125. /*****************************************************************************
  3126. *
  3127. * FUNCTION
  3128. *
  3129. * INPUT
  3130. *
  3131. * OUTPUT
  3132. *
  3133. * RETURNS
  3134. *
  3135. * AUTHOR
  3136. *
  3137. *   POV-Ray Team
  3138. *   
  3139. * DESCRIPTION
  3140. *
  3141. * CHANGES
  3142. *
  3143. ******************************************************************************/
  3144.  
  3145. static void Parse_Warp (Warp_Ptr)
  3146. WARP **Warp_Ptr;
  3147. {
  3148.   WARP *New = NULL;
  3149.   TURB *Turb;
  3150.   REPEAT *Repeat;
  3151.   BLACK_HOLE *Black_Hole;
  3152.   VECTOR Local_Vector;
  3153.  
  3154.   Parse_Begin();
  3155.  
  3156.   EXPECT
  3157.     CASE(TURBULENCE_TOKEN)
  3158.       New=Create_Warp(EXTRA_TURB_WARP);
  3159.       Turb=(TURB *)New;
  3160.       Parse_Vector(Turb->Turbulence);
  3161.       EXPECT
  3162.         CASE(OCTAVES_TOKEN)
  3163.           Turb->Octaves = (int)Parse_Float();
  3164.           if(Turb->Octaves < 1)
  3165.              Turb->Octaves = 1;
  3166.           if(Turb->Octaves > 10)  /* Avoid DOMAIN errors */
  3167.              Turb->Octaves = 10;
  3168.         END_CASE
  3169.  
  3170.         CASE (OMEGA_TOKEN)
  3171.           Turb->Omega = Parse_Float();
  3172.         END_CASE
  3173.  
  3174.         CASE (LAMBDA_TOKEN)
  3175.           Turb->Lambda = Parse_Float();
  3176.         END_CASE
  3177.         
  3178.         OTHERWISE
  3179.           UNGET
  3180.           EXIT
  3181.         END_CASE
  3182.       END_EXPECT
  3183.       EXIT
  3184.     END_CASE
  3185.  
  3186.     CASE(REPEAT_TOKEN)
  3187.       New=Create_Warp(REPEAT_WARP);
  3188.       Repeat=(REPEAT *)New;
  3189.       Parse_Vector(Local_Vector);
  3190.       Repeat->Axis=-1;
  3191.       if (Local_Vector[X]!=0.0) 
  3192.         Repeat->Axis=X;
  3193.       if (Local_Vector[Y]!=0.0)
  3194.         if (Repeat->Axis < X)
  3195.           Repeat->Axis=Y;
  3196.         else 
  3197.           Error("Can only repeat along 1 axis.");
  3198.       if (Local_Vector[Z]!=0.0)
  3199.         if (Repeat->Axis < X)
  3200.           Repeat->Axis=Z;
  3201.         else
  3202.           Error("Can only repeat along 1 axis.");
  3203.       if (Repeat->Axis < X)
  3204.         Error("No axis specified in repeat.");
  3205.       Repeat->Width=Local_Vector[Repeat->Axis];
  3206.          
  3207.       EXPECT
  3208.         CASE(OFFSET_TOKEN)
  3209.           Parse_Vector(Repeat->Offset);
  3210.         END_CASE
  3211.         
  3212.         CASE(FLIP_TOKEN)
  3213.           Parse_Vector(Repeat->Flip);
  3214.           if (Repeat->Flip[X]!=0.0) Repeat->Flip[X]=-1.0; else Repeat->Flip[X]=1.0;
  3215.           if (Repeat->Flip[Y]!=0.0) Repeat->Flip[Y]=-1.0; else Repeat->Flip[Y]=1.0;
  3216.           if (Repeat->Flip[Z]!=0.0) Repeat->Flip[Z]=-1.0; else Repeat->Flip[Z]=1.0;
  3217.         END_CASE
  3218.         
  3219.         OTHERWISE
  3220.           UNGET
  3221.           EXIT
  3222.         END_CASE
  3223.       END_EXPECT
  3224.       EXIT
  3225.     END_CASE
  3226.     
  3227.     CASE(BLACK_HOLE_TOKEN)
  3228.       New = Create_Warp(BLACK_HOLE_WARP) ;
  3229.       Black_Hole = (BLACK_HOLE *) New ;
  3230.       Parse_Vector (Local_Vector) ;
  3231.       Assign_Vector (Black_Hole->Center, Local_Vector) ;
  3232.       Parse_Comma () ;
  3233.       Black_Hole->Radius = Parse_Float () ;
  3234.       Black_Hole->Radius_Squared = Black_Hole->Radius * Black_Hole->Radius ;
  3235.       Black_Hole->Inverse_Radius = 1.0 / Black_Hole->Radius;
  3236.       Black_Hole->Strength = 1.0 ;
  3237.       Black_Hole->Power = 2.0 ;
  3238.       Black_Hole->Inverted = FALSE ;
  3239.       Black_Hole->Type = 0 ;
  3240.  
  3241.       EXPECT
  3242.         CASE(STRENGTH_TOKEN)
  3243.           Black_Hole->Strength = Parse_Float () ;
  3244.         END_CASE
  3245.  
  3246.         CASE(FALLOFF_TOKEN)
  3247.           Black_Hole->Power = Parse_Float () ;
  3248.         END_CASE
  3249.  
  3250.         CASE(INVERSE_TOKEN)
  3251.           Black_Hole->Inverted = TRUE ;
  3252.         END_CASE
  3253.  
  3254.         CASE(TYPE_TOKEN)
  3255.           Black_Hole->Type = (int) Parse_Float () ;
  3256.         END_CASE
  3257.  
  3258.         CASE(REPEAT_TOKEN)
  3259.           Parse_Vector (Black_Hole->Repeat_Vector) ;
  3260.           Black_Hole->Repeat = TRUE ;
  3261.           Check_BH_Parameters (Black_Hole) ;
  3262.         END_CASE
  3263.  
  3264.         CASE(TURBULENCE_TOKEN)
  3265.           Parse_Vector (Black_Hole->Uncertainty_Vector) ;
  3266.           Black_Hole->Uncertain = TRUE ;
  3267.           Check_BH_Parameters (Black_Hole) ;
  3268.         END_CASE
  3269.  
  3270.         OTHERWISE
  3271.           UNGET
  3272.           EXIT
  3273.         END_CASE
  3274.       END_EXPECT
  3275.       EXIT
  3276.     END_CASE
  3277.       
  3278.     CASE(SPIRAL_TOKEN)
  3279.       Error("Spiral warp not yet implemented.");
  3280.     END_CASE
  3281.  
  3282.     OTHERWISE
  3283.       Parse_Error_Str ("warp type");
  3284.     END_CASE
  3285.   END_EXPECT
  3286.  
  3287.   if (New==NULL)
  3288.   {
  3289.      Error("Empty warp statement.");
  3290.   }
  3291.   
  3292.   New->Next_Warp=*Warp_Ptr;
  3293.   *Warp_Ptr=New;
  3294.  
  3295.   Parse_End();
  3296. }
  3297.